09 Hot Updates Updating Service Parameters and Cloud Configuration Center

09 Hot Updates - Updating Service Parameters and Cloud Configuration Center #

Almost every project involves configuration parameters or configuration files. It is important to avoid hard coding and improve the security, timeliness, and flexibility of variable parameters through external configuration. In this article, we will discuss the configuration issues in software projects, especially in the context of microservices architecture.

Evolution of Parameter Configuration #

In the early days of software development, and even now in some cases, there was a situation of hard coding, where some variable parameters were hardcoded in the code. The disadvantages are obvious: when parameters change, the code must be rebuilt and the maintenance cost is high.

Later, the industry established rules and extracted some variable parameters to form configuration files in various formats, such as properties, yml, json, xml, etc. These parameters are centrally managed, and when changes occur, only the configuration files need to be updated. There is no need to recompile the code and build and deploy new code blocks. This is obviously more powerful than hard coding. However, there are also disadvantages:

  • Sensitive information is exposed in configuration files, which reduces security.
  • After configuration file changes, services also need to be restarted.

Then, distributed configuration emerged, decoupling the configuration parameters from the project. When the project uses them, it retrieves them from the configuration center or is notified by the configuration center when changes occur. The advantages are obvious:

  1. Eliminates the problem of exposing sensitive information.
  2. Configuration parameters no longer need to be coupled with code modules and can have flexible access control, thereby improving security.
  3. Configurations can take effect in real-time, which is helpful for scenarios with complex rules in the code.
  4. It can easily handle multi-environment deployments.

In the context of microservices, we also tend to use a distributed configuration center to manage configurations. When the number of service instances increases, there is no need to worry about the complexities of configuration.

Introduction to Open-Source Components #

Spring Cloud Config is a distributed configuration component under the Spring Cloud project. However, it cannot complete the configuration functionality on its own and needs the help of components such as Git or MQ to work together, making it slightly more complex.

Many companies in the industry have open-sourced distributed configuration components, such as Ctrip’s Apollo, Taobao’s Diamond, Baidu’s Disconf, Qihoo 360’s QConf, Alibaba’s Nacos, etc. Development based on components like ZooKeeper is also possible, and there are many options for technology selection.

In this case, Nacos is used as the selection. Why Nacos? First, it is a member of the Spring Cloud Alibaba project and closely fits into the ecosystem. Second, Nacos already serves as a service registry center, so it has the configuration center functionality built-in, without the need to introduce additional third-party components, reducing system complexity. It combines the functionalities of Spring Cloud Config and Eureka into one component.

Nacos locates unique configuration items through DataId and Group at the underlying level, and supports different configuration formats such as JSON, TEXT, YAML, etc., each with its own syntax rules.

Nacos Configuration Management #

Taking the example of a system that binds users’ mobile phone numbers, suppose a shopping mall is running a promotion where users who bind their mobile phone numbers and open a monthly card will receive double the points, as well as the chance to win a special gift package. After the promotion ends, the system needs to revert to its original state. This is a frequently seen gameplay.

Add the jar dependency in the pom.xml of the parking-member project. However, in the early stages, we have already applied the service registry functionality of Nacos, so it has already been introduced into the project.

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

Next, configure the connection with Nacos. Since there are two types of configuration files in a Spring Boot project, one is the application configuration and the other is the bootstrap configuration, where should we put the configuration? Let’s first understand the difference between bootstrap and application.

img

(Screenshot from the official documentation: https://cloud.spring.io/spring-cloud-static/Greenwich.SR1/single/spring-cloud.html#thebootstrapapplicationcontext)

Nacos configuration is consistent with spring-cloud-config and must be placed in the bootstrap.yml or bootstrap.properties file. Configurations written in the application.properties or application.yml file will be ineffective.

bootstrap.properties:

spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.profiles.active=dev
spring.application.name=member-service
spring.cloud.nacos.config.shared-data-ids=${spring.application.name}-${spring.profiles.active}.properties
spring.cloud.nacos.config.refreshable-dataids=${spring.application.name}-${spring.profiles.active}.properties

The reason for dynamically configuring using spring.application.name-spring.application.name-${spring.profiles.active} is to prepare for multi-environment construction in the future. Of course, you can directly hard-code the Nacos configuration file, but this is not conducive to scalability and maintenance. The refreshable-dataids configuration item is not required, but if it is missing, all Nacos configuration items will not be automatically refreshed. You must find another way to refresh the configuration items in order to apply them to the service.

Using Configuration Items in Code #

In the method where the user binds their mobile number, define an inner variable to receive the parameter value from the configuration center. You can directly use Spring’s @Value annotation to retrieve the value. It can be used in the Controller layer or Service layer. The class must be annotated with @RefreshScope in order to synchronize the value in real-time.

In Nacos, define two configuration items onoff_bindmobile and on_bindmobile_mulriple, which represent a switch and a score multiplier, respectively. At the same time, define two local variables to receive the values of the two configuration items in Nacos.

Even after externalizing the parameters as configurations, the code must reserve a position for the logic to switch. That is, this logic is pre-placed in the code. Whether to execute the logic, related branches in the logic, etc., entirely depend on the value of the configuration parameter. For example, during registration, there are often activities such as giving points, giving coupons for registration, and the value of the coupons, with the chance of winning a prize. When one activity ends, it automatically switches to another activity. If this logic is not pre-placed, the code cannot execute this logic.

The complete code is as follows:

@Value("${onoff_bindmobile}")
private boolean onoffBindmobile;

@Value("${on_bindmobile_mulriple}")
private int onBindmobileMulriple;

@Override
public int bindMobile(String json) throws BusinessException{
    Member member = JSONObject.parseObject(json, Member.class);
    int rtn = memberMapper.insertSelective(member);

    //invoke another service
    if (rtn > 0) {
        MemberCard card = new MemberCard();
        card.setMemberId(member.getId());
        //Check if the switch is turned on
        if (onoffBindmobile) {
            //special logic
            card.setCurQty("" +50 * onBindmobileMulriple);
        } else {
            //normal logic
            card.setCurQty("50");
        }

        memberCardClient.addCard(JSONObject.toJSONString(card));
        log.info("creata member card suc!");
    }

    return rtn;
}

Configuring Parameters in Nacos #

The bootstrap configuration file has made a convention: the key and value format of the configuration item is the same as a properties file. Open the Nacos console and go to the “Configuration Management” -> “Configuration List” page, then click on “New” in the top right corner.

img

Enter the two configuration items defined above. The configuration items can be customized to meet the requirements of multiple environment configurations. In other environments, create corresponding configurations. Enter the Data ID, such as member-service-prd.properties or member-service-uat.properties. The Group can use the default value, and if necessary, a Group value needs to be defined. Save it.

The value type of the configuration item needs to be consistent with the agreed type in the code, otherwise, there may be parsing errors.

To change the value of a configuration item, modify it and publish it. You can see that the value of the configuration item takes effect immediately. This is mainly achieved through the @RefreshScope annotation mentioned above and the spring.cloud.nacos.config.refreshable-dataids configuration in the bootstrap configuration file. If either of them is missing, the configuration item will only take effect after restarting the application, which contradicts the maintainability and robustness of our program.

You can fill in the configuration center with the corresponding database connection, access keys for third-party applications, and frequently changed parameter items. With the permission control of the configuration center itself, you can ensure that sensitive items are not leaked, and good configuration isolation can be achieved for different deployment environments.

With this, the configuration center based on Nacos is configured, and according to this configuration, it can be smoothly migrated to other services. Let’s leave a question: using externalized configurations like properties files is quite common in projects. How can we ensure that critical information is not leaked, such as the username and password for the database, and the core keys for third parties?