01 actual combat of Nacos configuration center
Introduce dependency
<!--nacos Configuration center--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency>
The priority of the configuration file is from high to low
# ${spring.application.name}-${profile}.${file-extension:properties} #${spring.application.name}.${file-extension:properties} #${spring.application.name} #extensionConfigs nacos.yml #sharedConfigs multiple microservices public configuration redis
@RestController @RefreshScope // This annotation can sense changes in value public class TestController { @Value("${common.age}") private String age; @GetMapping("/common") public String hello() { return age; } }
In bootstrap Configure in the properties file. You can configure profile / namespace / group / dataId (directly specify the file name). The dataId can also be shared sharedConfigs or independent extensionConfigs
spring.application.name=nacos-config # Configuration center address spring.cloud.nacos.config.server-addr=127.0.0.1:8848 # Close configuration center #spring.cloud.nacos.config.enabled = false # Configuration method of file extension with dataid yaml # `${spring.application.name}.${file-extension:properties}` spring.cloud.nacos.config.file-extension=yaml #Profile granularity configuration ` ${spring. Application. Name} - ${profile}$ {file-extension:properties}` # nacos-config-prod.yaml spring.profiles.active=prod #Customize the configuration of the namespace spring.cloud.nacos.config.namespace=39e1e969-15f9-46d2-832d-fa052da55377 # Custom Group configuration spring.cloud.nacos.config.group=DEFAULT_GROUP # Custom Data Id configuration #Common configurations of different projects support shared dataid redis spring.cloud.nacos.config.sharedConfigs[0].data-id= common.yaml spring.cloud.nacos.config.sharedConfigs[0].group=DEFAULT_GROUP spring.cloud.nacos.config.sharedConfigs[0].refresh=true # config external configuration # Supports the configuration of one application with multiple dataids yml mybatis. yml spring.cloud.nacos.config.extensionConfigs[0].data-id=nacos.yaml spring.cloud.nacos.config.extensionConfigs[0].group=REFRESH_GROUP spring.cloud.nacos.config.extensionConfigs[0].refresh=true
Spring boot and nacos integration
<dependency> <groupId>com.alibaba.boot</groupId> <artifactId>nacos-config-spring-boot-actuator</artifactId> <version>${nacos-config-spring-boot.version}</version> </dependency>
application. That's enough for the properties configuration file, Nacos config. server-addr=127.0.0.1:8848
@SpringBootApplication // Configure which dataId to use as the data source @NacosPropertySource(dataId = "example", autoRefreshed = true) public class NacosConfigApplication { public static void main(String[] args) { SpringApplication.run(NacosConfigApplication.class, args); } } @Controller @RequestMapping("config") public class ConfigController { // Get the value of this configuration @NacosValue(value = "${useLocalCache:false}", autoRefreshed = true) private boolean useLocalCache; @RequestMapping(value = "/get", method = GET) @ResponseBody public boolean get() { return useLocalCache; } }
02 analysis of Nacos configuration center architecture
03 source code analysis of Nacos config client
Entry: interface core method
What is the priority of multiple configurations
springboot load attribute configuration: org springframework. boot. env. The propertysourceloader interface has two implementation classes
Take the load method of an implementation class as its entry org springframework. boot. env. PropertiesPropertySourceLoader#load
During the startup process, the run method of SpringApplication is also followed, and the ApplicationEnvironmentPreparedEvent environment preparation event is released. The org \ springframework \ cloud \ bootstrap \ bootstrap applicationlistener listener is triggered, and the springboot method is called back during the process. Configurableenvironment environment = this prepareEnvironment(listeners, applicationArguments); The event is also passed to the spring boot listener ConfigFileApplicationListener, which will load all configuration files. In the process, the PropertiesPropertySourceLoader#load method loads bootstrap Properties, and then load application properties...
04 how does the client get the configuration from the configuration center
The main method to obtain the configuration is the getConfig method of the NacosConfigService class. Usually, this method directly obtains the configuration value from the local file. If the local file does not exist or the content is empty, then pull the configuration from the remote through the HTTP GET method and save it to the local snapshot. When obtaining remote configuration through HTTP , Nacos , provides two fusing strategies, one is the timeout time, the other is the maximum number of retries, and the default is three retries.
05 how does the Client perceive the change of configuration in the configuration center
After all configuration files are loaded, a corresponding listener will be added to all dataid s. A thread in the background will regularly check the configuration file information. After finding that the file md5 has changed, the listener's method will be triggered. RefreshEvent will be published inside the method. This RefreshEventListener will trigger the refresh of ContextRefresher to refresh the environment, When replacing the previous environment, the bean modified by the annotation @ RefreshScope will be stored in a container, and the old bean will be remove d and replaced with a new bean
06 source code analysis of Nacos config server
public class ConfigServerDemo { public static void main(String[] args) throws NacosException, InterruptedException { String serverAddr = "localhost:8848"; String dataId = "nacos-config-demo.yaml"; String group = "DEFAULT_GROUP"; Properties properties = new Properties(); properties.put(PropertyKeyConst.SERVER_ADDR, serverAddr); //Get configuration center service ConfigService configService = NacosFactory.createConfigService(properties); //Pull configuration from configuration center String content = configService.getConfig(dataId, group, 5000); System.out.println(content); //Register listener configService.addListener(dataId, group, new Listener() { @Override public void receiveConfigInfo(String configInfo) { System.out.println("Perceived configuration change:" + configInfo); } @Override public Executor getExecutor() { return null; } }); //Publish configuration send properties format configService.publishConfig(dataId,group,"common.age=30", ConfigType.PROPERTIES.getType()); Thread.sleep(3000); //Pull configuration from configuration center content = configService.getConfig(dataId, group, 5000); System.out.println(content); Thread.sleep(Integer.MAX_VALUE); } }
07 how do other nodes synchronize configuration data under the cluster architecture
When the server starts, it will rely on the # init # method of # DumpService # to load # configuration from the database and store it on the local disk, and cache some important meta information, such as # MD5 # value in memory. According to the last heartbeat time saved in the heartbeat file, the server will determine whether to dump the full configuration data or part of the incremental configuration data from the database (if the last heartbeat interval of the machine is less than 6 h).
Of course, first empty the disk cache, and then fetch 1000 configurations each time according to the primary key ID and brush them into the disk and memory. Incremental {dump} is to retrieve the new configurations (including updated and deleted) in the last six hours. First refresh the memory and files according to this batch of data, and then compare the database according to the total amount of all data in the memory. If there are changes, synchronize again. Compared with the total amount of} dump}, it will reduce a certain number of database} IO} and disk} IO} times.
If you want to change the mysql configuration and update it to the client immediately, you need to write a listener to listen for changes and publish a ConfigDataChangeEvent event. Otherwise, the server will not be aware of it without restarting.