Implementation and Practice of Nacos Configuration Center

1. Background

At present, each team of our company uses different configuration centers. The e-commerce company uses Spring Cloud Config, the payment uses Apollo, and the APP team uses Apollo+Nacos. In order to better cope with the development of the company's business, a unified infrastructure technology stack is essential.

image-20220222140242719

Image source: Live broadcast "How to do a good job in microservice infrastructure selection" – Li Yunhua

In addition, the Spring Cloud Config used by the e-commerce team faces the following technical pain points:

  • Modifying the configuration requires restarting the service
  • Configuration management is not friendly (modified through gitlab)
  • Lack of features such as permission control, format inspection, and security configuration

2. Configuration center selection

Open source product analysis

  • Spring Cloud Config

Open source in September 2014, Spring Cloud ecological components can be seamlessly integrated with the Spring Cloud system.

  • Apollo

In May 2016, Ctrip open sourced a reliable distributed configuration management center. It can centrally manage the configuration of different environments and different clusters of applications. After the configuration is modified, it can be pushed to the application side in real time, and it has the characteristics of standardized permissions and process governance. It is suitable for microservice configuration management scenarios.

  • Nacos

In June 2018, Ali open sourced a dynamic service discovery, configuration management, and service management platform that is easier to build cloud-native applications. It was incubated in Alibaba and grew up in the peak test of Double Eleven in ten years. It has accumulated the core competitiveness of being easy to use, stable and reliable, and excellent performance.

comparison item Nacos Apollo Spring Cloud Config
Community activity open source time 2018.6 2016.5 2014.9
github follow 20.5k 26K 1.7K
document Complete Complete Complete
performance Stand-alone read (QPS) 15000 9000 7 (due to current limitation)
Stand-alone write (QPS) 1800 1100 5 (due to current limitation)
availability Impact of service shutdown (configuration service) Started clients do not affect Started clients do not affect Started clients do not affect
deployment mode cluster cluster cluster
ease of use Configuration effective time real time real time Restart to take effect, or manual refresh to take effect
data consistency HTTP asynchronous notification The database simulates the message queue, and Apollo regularly reads the message for one minute to take effect in real time Git guarantees data consistency, and Config-server reads data from Git
configuration interface support support not support
Configuration format check support support not support
configuration rollback support support Supported (git-based rollback)
version management support support Support (git-based version management)
Client Supported Languages Official java Unofficial Go, Python, NodeJS, C++ Official java .net Unofficial Go, Python, NodeJS, PHP, C++
client use nacos client apollo client cloud config client
safety authority management support Complete data permissions are relatively complete support (git)
Authorization/Audit/Review support Direct operation on the interface and support separation of modification and publishing permissions Rely on git permission management
data encryption not support not support Encrypt and Decrypt Property Values
architectural complexity Operation and maintenance cost Nacos+MySQL (simple deployment) Config+Admin+Portal+MySQL (complex deployment) Config-server+Git+MQ (complex deployment)
service dependency It is the registration and discovery center of Alibaba Cloud. The two functions are separated. Distributed requires registration center with built-in eureka Registry required
Gray release Support client configuration and routing rule client computing coupling is high and cumbersome Supports server-side configuration and routing rules server-side calculation client is transparent and simple support
mail service not support support not support
Query configuration monitoring support support support
  1. From the perspective of performance: read and write performance Nacos > Apollo > Spring Cloud Config.
  2. From the perspective of function: function completeness Apollo > Nacos > Spring Cloud Config.
  3. From the perspective of community activity: it turns out that Spring Cloud’s ecological Netflix basically doesn’t maintain much, because it doesn’t make money; but Spring Alibaba’s microservice ecosystem will always be open source and maintained, because Ali makes money after converting this piece of SaaS.
  4. Advantages of Nacos: Simple. It integrates the registration center and configuration center functions, and its deployment and operation are more intuitive and simpler than Apollo, so it simplifies the complexity of the architecture and reduces the work of operation and maintenance and deployment.

performance comparison

  • Press information

Processor: Intel® Core™ i5-9500 CPU @ 3.00GHz 3.00 GHz

System: windows 10

Internal test: 16G

  • Pressure measurement tool: JMeter
  • Pressure test strategy: 100 users request thread 10 incrementally open, duration 100s

Scenario 1: Calling the server

image-20220222142033442

The test results are as follows:

image-20220222142102625

Through the pressure test, it is found that the TPS of Nacos read configuration is about 11,000, and the TPS of write configuration is about 1800, while the TPS of Apollo read configuration is about 1100, and the TPS of write configuration is about 310. Nacos has obvious advantages in read and write performance.

Scenario 2: Call the client

image-20220222142123826

The test results are as follows:

image-20220222142232508

It can be seen that the read performance is not much different.

in conclusion

Reason for selection Reason for not choosing
Nacos Unified technology stack can solve the pain points of existing technologies Low operation and maintenance costs
Apollo Rely on Eureka
Spring Cloud Config

Reference documents:

3. Quick use

Reference document: https://nacos.io/en-us/docs/quick-start-spring-boot.html

upgrade dependencies

Remove spring-cloud-config dependency:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>

Add Nacos dependency:

<dependency>
    <groupId>com.alibaba.boot</groupId>
    <artifactId>nacos-config-spring-boot-starter</artifactId>
    <version>0.1.8</version>
</dependency>

Replace Nacos configuration

Replace the config configuration in the original bootstrap.yml file with the nacos configuration.

spring:
  application:
    name: {
    
    应用名}
  cloud:                                                      # 移除
    config:                                                   # 移除
      uri: http://config-center.alpha-intra.dbses.com/conf    # 移除
      label: alpha                                            # 移除

The replacement results are as follows:

spring:
  application:
    name: {
    
    应用名}
nacos:
  config:
    server-addr: http://ec-nacos.dbses.com
    namespace: alpha
    group: {
    
    组名}

Add annotations to the startup class

// dataId 对应服务的配置
@NacosPropertySource(groupId = "${nacos.config.group}", dataId = "${spring.application.name}.yml", first = true)
public class WebApplication {
    
    
 
    public static void main(String[] args) {
    
    
        SpringApplication.run(WebApplication.class, args);
    }
 
}

4. Practice

Configure Dynamic Refresh

Method 1: Use @NacosValue

To use this method, you need to add autoRefreshed=true to @NacosPropertySource. The sample code is as follows:

@NacosPropertySource(groupId = "infra", dataId = "zebra-service.yml", first = true, autoRefreshed = true)
public class WebApplication {
    
    
 
    public static void main(String[] args) {
    
    
        SpringApplication.run(WebApplication.class, args);
    }
 
}

Nacos is configured as follows:

test1:
  config: 2

The interface code is as follows:

@RestController
public class TestController {
    
    
 
    @NacosValue(value = "${test1.config}", autoRefreshed = true)
    private String config;
 
    @GetMapping("/config")
    public String getConfig() {
    
    
        return config;
    }
 
}

Method 2: Use @NacosConfigurationProperties

The sample code is as follows:

@Configuration
@Data
@NacosConfigurationProperties(prefix = "test2", dataId = "zebra-service.yml", groupId = "infra", autoRefreshed = true)
public class TestConfig {
    
    
 
    private List<String> config;
 
    private Map<String, String> map;
 
    @Override
    public String toString() {
    
    
        return "TestConfig{" + "config=" + config + ", map=" + map + '}';
    }
 
}

Nacos is configured as follows:

test2:
  config:
    - yang
    - wang
  map:
    courier: yang
    zebra: wang

The interface code is as follows:

@RestController
public class TestController {
    
    
 
    @Autowired
    private TestConfig testConfig;
 
    @GetMapping("/config2")
    public String getConfig2() {
    
    
        return testConfig.toString();
    }
 
}

Notice

Refresh the map dynamically, the modified key will be accumulated, and the original key will not be deleted. For example, after changing test2.map.zebra in zebra-service.yml configuration to test2.map.zebr, the obtained results are as follows:

TestConfig{config=[yang, money], map={courier=yang, zebra=money, zebr=money}}

Method 3: Use @NacosConfigListener

Nacos is configured as follows:

test1:
  config: 2

The sample code is as follows:

@RestController
public class TestController {
    
    
 
    @Value(value = "${test1.config}")
    private String config;
 
    @GetMapping("/config")
    public String getConfig() {
    
    
        return config;
    }
 
    @NacosConfigListener(dataId = "zebra-service.yml", groupId = "infra")
    public void testConfigChange(String newContent) {
    
    
        YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean();
        yamlFactory.setResources(new ByteArrayResource(newContent.getBytes()));
        Properties commonsProperties = yamlFactory.getObject();
        this.config = commonsProperties.getProperty("test1.config"));
    }
 
}

Importing multiple configurations

Problem Description

Our project has read many public configurations before, and now we want to read public configurations, what should we do?

problem solved

Multiple configuration files can be added using the @NacosPropertySources annotation.

Sample code:

@NacosPropertySources({
    
    
        @NacosPropertySource(groupId = "infra", dataId = "captcha-service.yml", first = true),
        @NacosPropertySource(groupId = "commons", dataId = "__common_eureka_.yml")
})
public class WebApplication {
    
    
 
    public static void main(String[] args) {
    
    
        SpringApplication.run(WebApplication.class, args);
    }
 
}

Here first = true means that the configuration priority of this file is the highest.

local configuration override

Problem Description

As a developer, we may need to start the program locally for debugging, but at this time the locally started program is connected to the configuration of the alpha environment. If you modify the configuration of the alpha environment, it may affect the operation of alpha and other programs.

Faced with this situation, how do we manage the priority of configuration?

Let's take the test1.config configuration as an example. The nacos configuration file is as follows:

image-20220222143101832

The startup configuration is as follows:

image-20220222143133401

The test code is as follows:

@RestController
public class TestController {
    
    
 
    @NacosValue(value = "${test1.config}", autoRefreshed = true)
    private String config1;
 
    @GetMapping("/config1")
    public String getConfig1() {
    
    
        return config1;
    }
}

The execution result is:

image-20220222143208909

The local configuration does not achieve the effect of coverage.

problem analysis

We might as well transform the program startup class first.

image-20220222143652521

It can be seen from the breakpoint that the priority of the application configuration (here refers to zebra-service.yml in nacos, the same below) is before the public configuration, which is necessary.

App config must precede public config.

But the application configuration is also before the system variables (systemProperties) and the system environment (systemEnvironment). So the test1.config we configured did not take effect as local.

With a slight modification:

image-20220222143612121

problem solved

Then test whether the local configuration is overwritten.

image-20220222143742655

The local configuration has reached the effect of coverage. The final startup class code is:

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@PrepareConfigurations({
    
    "__common_database_", "__common_eureka_"})
@NacosPropertySource(groupId = "infra", dataId = "zebra-service.yml", autoRefreshed = true
        ,after = StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME
)
public class WebApplication {
    
    
 
    public static void main(String[] args) {
    
    
        SpringApplication.run(WebApplication.class, args);
    }
 
}

This article is published by OpenWrite, a multi-post platform for blogging !

Guess you like

Origin blog.csdn.net/yang237061644/article/details/127464867