Author: MaltCopy the code

This article uses the open source version below

Nacos Server version: 1.4.1

Nacos config-start version: 2.2.5-release

The first thing to say is ~

Why read the source code:

1, improve technical skills: ** study the excellent design ideas in the source code, such as the solution of some difficult problems, and some excellent design patterns, overall improve their technical skills

2, the depth of the technical framework: ** source code read more, for a new technology or framework to master the speed will be greatly improved, see the framework demo can roughly know the underlying implementation, technical framework update again fast is not afraid

3, ** quickly locate online problems: ** encounter online problems, especially in the framework source code problems (such as bugs), can quickly locate, this is compared to other people who have not seen the source of the advantage

4, the government knows what it is: the people who pursue technology will do, using a good framework, would like to know how to achieve the bottom

5. Embrace the open source community: ** participates in the research and development of open source projects, makes more contacts and accumulates more high-quality contacts

Look at the source method:

1, ** first use: ** first read the official documents to quickly grasp the basic use of the framework

2, ** grasp the main line: ** find a demo to start with, follow the ropes quickly static look at the main source of the framework, draw the main process of the source code, do not start into the details of the source code, otherwise they will put their own halo, guess by experience

3, ** drawing and taking notes: * * summarizes the framework of some core functions, from the function point into the details of the source, while watching the source code source code to figure, and the understanding of the key source to take notes, recording all the bright spots in the source code, subsequent reference to work in the project, also can see the source code while the debug source implementation process, the value of some of the key variables

4, ** integration summary: ** all function points of the source are analyzed, back to the main process diagram to comb again, and strive to draw all their pictures in the head to do an integration

1. What is Nacos?

IO/zh-CN /docs/…

**Nacos is dedicated to helping you discover, configure, and manage microservices. Nacos provides an easy-to-use feature set that helps you quickly implement dynamic service discovery, service configuration, service metadata, and traffic management. ** Key features of Nacos include:

  • Service discovery and service health monitoring

  • Dynamically configured service

  • Dynamic DNS Service

  • Services and their metadata management

1.1 Nacos architecture

NamingService: NamingService, the core interface of the registry

ConfigService: Configures services and core interfaces

IO/zh-CN /docs/…

2. Nacos Registry

2.1 Nacos registry structure

2.2 Nacos Registry core functions

  • Service registration: The Nacos Client registers its services with the Nacos Server by sending REST requests, providing its own metadata, such as IP addresses and ports. When Nacos Server receives the registration request, it stores the metadata information in a two-tier memory Map.

  • Service heartbeat: After a service is registered, the Nacos Client maintains a timed heartbeat to continuously notify the Nacos Server that the service is always available and prevents it from being rejected. By default, heartbeat is sent every 5 seconds.

  • Service synchronization: Nacos Server clusters synchronize service instances with each other to ensure the consistency of service information. leader raft

  • Service discovery: When the service consumer (Nacos Client) invokes the service provider’s service, it sends a REST request to the Nacos Server to obtain the list of services registered above, which is cached locally in the Nacos Client. At the same time, a scheduled task is started in Nacos Client to periodically pull the server’s latest registry information to the local cache

  • Service health check: Nacos Server starts a scheduled task to check the health of registered service instances, sets its healthy attribute to false for instances that have not received a client heartbeat for more than 15 seconds (the client service does not detect it), and if an instance has not received a heartbeat for more than 30 seconds, Reject the instance directly (the deleted instance is re-registered if the heartbeat is resumed)

2.3 Spring Cloud Alibaba Nacos Start quickly

IO/zh-CN /docs/…

3. Source code analysis of Nacos Registry

Source code process or around the core functions, specifically for the following aspects:

Service registration: The Nacos Client registers its services with the Nacos Server by sending REST requests, providing its own metadata, such as IP addresses and ports. When Nacos Server receives the registration request, it stores the metadata information in a two-tier memory Map.

Service heartbeat: After a service is registered, the Nacos Client maintains a timed heartbeat to continuously notify the Nacos Server that the service is always available and prevents it from being rejected. By default, heartbeat is sent every 5 seconds.

Service health check: Nacos Server starts a scheduled task to check the health of registered service instances, sets its healthy attribute to false for instances that have not received a client heartbeat for more than 15 seconds (the client service does not detect it), and if an instance has not received a heartbeat for more than 30 seconds, Reject the instance directly (the deleted instance is re-registered if the heartbeat is resumed)

Service discovery: When the service consumer (Nacos Client) invokes the service provider’s service, it sends a REST request to the Nacos Server to obtain the list of services registered above, which is cached locally in the Nacos Client. At the same time, a scheduled task is started in Nacos Client to periodically pull the server’s latest registry information to the local cache

Service synchronization: Nacos Server clusters synchronize service instances with each other to ensure the consistency of service information.

Detailed source flow chart:

https://www.processon.com/view/link/60f7e7d3e0b34d16fa90a72f

The process involves communicating with the server through a REST interface.

IO /zh-cn/docs/…

[

] (www.processon.com/view/link/6)…

4. Nacos Configuration center

4.1 Use of the Nacos configuration center

Reference official: github.com/alibaba/spr…

4.2 Config Related configuration

Nacos data model keys are uniquely determined by triples, Namespace defaults to empty strings, common namespaces (public), and groups default to DEFAULT_GROUP

  • Dynamic configuration update is supported

When the dynamic configuration is refreshed, it is updated to the Enviroment, so the configuration is fetched from the Enviroment every second

@SpringBootApplication public class NacosConfigApplication { public static void main(String[] args) throws InterruptedException { ConfigurableApplicationContext applicationContext = SpringApplication.run(NacosConfigApplication.class, args); While (true) {// When the dynamic configuration is refreshed, it is updated to the Enviroment, So here are extracted from every two seconds in the Enviroment configuration String userName = applicationContext. GetEnvironment () getProperty (" common. The name "); String userAge = applicationContext.getEnvironment().getProperty("common.age"); System.err.println("common name :" + userName + "; age: " + userAge); TimeUnit.SECONDS.sleep(1); }}}Copy the code
  • Profile granularity configuration is supported

Spring-cloud-starter-alibaba-nacos-config when loading the configuration, Not just for spring loaded with dataid. Application. Name. {spring. Application. The name}. Spring. Application. Name. {file – the extension: the properties} Is the basic configuration of the prefix. Name −{spring.application. Name}-spring.application. Name −{profile}. File − Extension: Basic configuration of properties. In daily development, if you encounter different configurations in multiple environments, you can use the basic configuration of {file-extension:properties} provided by Spring. If you encounter different configurations in multiple environments during daily development, you can use the basic configuration of File − Extension: Properties provided by Spring. In daily development, if you encounter different configurations in multiple environments, you can use the {spring.profiles.active} configuration item provided by Spring to configure the configurations.

spring.profiles.active=dev
Copy the code
  • You can customize a namespace

Used for configuration isolation of tenant granularity. Different namespaces can have the same Group or Data ID configuration. One of the common scenarios for a Namespace is the separation of configurations in different environments, such as the separation of assets (such as configurations and services) between the development test environment and the production environment.

Without explicitly specify ${spring. Cloud. Nacos. Config. The namespace} configuration, the default is used on Public nacos this namespace. To use a custom namespace, you can perform the following operations:

spring.cloud.nacos.config.namespace=71bb9785-231f-4eca-b4dc-6be446e12ff8
Copy the code
  • Supports the configuration of user-defined groups

A Group is one of the dimensions of an organization configuration. Configuration sets are grouped by a meaningful string, such as Buy or Trade, to distinguish between configuration sets with the same Data ID. When you create a configuration on Nacos, DEFAULT_GROUP is used by default if the name of the configuration group is not specified. A common scenario for configuring groups: different applications or components use the same configuration type, such as database_URL configuration and MQ_topic configuration.

Without explicitly specify ${spring. Cloud. Nacos. Config. Group} configuration, the default is DEFAULT_GROUP. If you need to customize your own Group, you can perform the following configuration:

spring.cloud.nacos.config.group=DEVELOP_GROUP
Copy the code
  • Supports custom extended Data Id configuration

The Data ID is one of the dimensions of the organization partition configuration. The Data ID is typically used to organize the configuration set that divides the system. A system or application can contain multiple configuration sets, each of which can be identified by a meaningful name. Data ID usually use class Java packages (such as com. Taobao. Tc. Refund. The level) the naming rules to ensure the global uniqueness. This naming rule is optional.

The customized extended Data Id configuration not only solves the configuration sharing problem among multiple applications, but also supports multiple configuration files for one application.

# # custom Data Id configuration of different engineering general configuration support Shared DataId spring. Cloud. Nacos. Config. SharedConfigs [0]. The Data - Id = common. The yaml spring.cloud.nacos.config.sharedConfigs[0].group=REFRESH_GROUP spring.cloud.nacos.config.sharedConfigs[0].refresh=true # Config External Configuration # Support multiple DataId configurations spring.cloud.nacos.config.extensionConfigs[0].data-id=ext-config-common01.properties spring.cloud.nacos.config.extensionConfigs[0].group=REFRESH_GROUP spring.cloud.nacos.config.extensionConfigs[0].refresh=true spring.cloud.nacos.config.extensionConfigs[1].data-id=ext-config-common02.properties spring.cloud.nacos.config.extensionConfigs[1].group=REFRESH_GROUPCopy the code

4.2 Configuring priorities

Spring Cloud Alibaba Nacos Config currently offers three configuration capabilities to pull relevant configurations from Nacos.

  • A: by the spring. Cloud. Nacos. Config. The Shared – configs support multiple Shared Data Id configuration

  • B: by the spring. Cloud. Nacos. Config. Ext – config [n]. The data – id way to support multiple extended data id configuration

  • C: Data Id configurations are automatically generated based on internal rules (application name, application name + Profile)

When the three approaches are used together, one of their priorities is :A < B < C

Priority from high to low:

  1. Nacos-config-product. yaml Precise configuration

  2. Nacos-config. yaml common configuration for different engineering environments

  3. Ext-config: Different project extension configurations

  4. Shared-dataids common configuration for different projects

4.5 @ RefreshScope

The @Value annotation can get the Value of the configuration center, but it cannot dynamically sense the changed Value, so the @refreshScope annotation needs to be used

@RestController @RefreshScope public class TestController { @Value("${common.age}") private String age; @GetMapping("/common") public String hello() { return age; }}Copy the code

5. Source code analysis of Nacos configuration center

Detailed source flow chart:

www.processon.com/view/link/6…

5.1 Configuring the Central Architecture

The configuration center uses Demo

public class ConfigServerDemo { public static void main(String[] args) throws NacosException, InterruptedException { String serverAddr = "localhost"; String dataId = "nacos-config-demo.yaml"; String group = "DEFAULT_GROUP"; Properties properties = new Properties(); properties.put(PropertyKeyConst.SERVER_ADDR, serverAddr); / / get configuration services ConfigService ConfigService = NacosFactory. CreateConfigService (properties); String content = ConfigService. getConfig(dataId, group, 5000); System.out.println(content); / / registered listeners configService. AddListener (dataId group, new Listener() { @Override public void receiveConfigInfo(String configInfo) { System.out.println("===recieve:" + configInfo); } @Override public Executor getExecutor() { return null; }}); / / release configuration / / a Boolean isPublishOk = configService. PublishConfig (dataId, group, "content"); //System.out.println(isPublishOk); / / send the format of the properties configService. PublishConfig (dataId group, "common. Age = 30", ConfigType. Properties. The getType ()); Thread.sleep(3000); content = configService.getConfig(dataId, group, 5000); System.out.println(content); // boolean isRemoveOk = configService.removeConfig(dataId, group); // System.out.println(isRemoveOk); // Thread.sleep(3000); // content = configService.getConfig(dataId, group, 5000); // System.out.println(content); // Thread.sleep(300000); }}Copy the code

5.2 NacOS Config Client source code

Configure the central core interface ConfigService

5.2.1 Obtaining the Configuration

The main method to obtain the configuration is the getConfig method of the NacosConfigService class. Usually, this method obtains the configuration value directly from the local file. If the local file does not exist or the content is empty, the method uses the HTTP GET method to pull the configuration from the remote end and saves the configuration to the local snapshot. Nacos provides two fusing policies when obtaining remote configurations over HTTP: timeout and maximum number of retries (three by default).

5.2.2 Registering listeners

The configuration center client registers listeners for configuration items to perform callbacks when configuration items change

  • NacosConfigService#getConfigAndSignListener

  • ConfigService#addListener

Nacos can register listeners in this way, and their internal implementations all call addCacheDataIfAbsent of the ClientWorker class. CacheData is an instance that maintains a configuration item and all listeners registered under it. All CacheData is stored in an atom called cacheMap in the ClientWorker class. Its core members are:

5.2.3 Configuring Long Polling

ClientWorker configures long polling through two thread pools: a single-threaded executor that fetches cacheData instances for polling every 3,000 cacheData entries every 10ms. Package it as a LongPollingTask and submit it to a second thread pool for executorService processing.

5.3 NacOS Config Server source code analysis

5.3.1 configuration dump

When the server starts up, it relies on the init method of DumpService, stores the load configuration from the database on the local disk, and caches some important meta information, such as THE MD5 value, into the memory. The server determines whether to dump all configuration data or some incremental configuration data from the database based on the last heartbeat time saved in the heartbeat file (if the last heartbeat interval is less than 6 hours).

Full dump clears the disk cache and flushes 1000 configurations at a time to disk and memory based on the primary key ID. Incremental dump is to retrieve the newly added configurations (including updated and deleted configurations) in the last 6 hours, refresh the memory and files based on this batch of data, and compare the database with all the data in the memory. If there is any change, then synchronize the data again. Compared with full dump, it can reduce the number of database I/O and disk I/O.

5.3.2 Configuring publishing

The code to publish the configuration is located in ConfigController#publishConfig. In clustered deployment, requests are initially made to only one machine, which inserts the configuration into Mysql for persistence. Instead of accessing MySQL for every configuration query, the server relies on the dump function to cache the configuration in a local file. Therefore, after a single machine has saved the configuration, it needs to notify other machines to refresh the memory and file contents in the local disk. Therefore, it will issue an event named ConfigDataChangeEvent, which will notify all cluster nodes (including itself) through HTTP calls, triggering the local file and memory refresh.

5.3.3 Handling Long Polling

The client side has a long polling task that pulls configuration changes on the server side. The server side processes the logic in the LongPollingService class. There is a Runnable task named ClientLongPolling. The server wraps the polling request it receives as a ClientLongPolling task, which holds an AsyncContext response object and executes 29.5s later through a timed thread pool. The return time is 500ms earlier than the client timeout time of 30 seconds to ensure that the client will not time out due to network delay.