Service Configuration Status

Configuration files are familiar to us all. In microservice system, each microservice not only has code, but also needs to “connect other resources”, such as database configuration or functional switch of MySQL, Redis, Security and other related configurations. In addition to the basic configuration of project operation, there are also some configurations related to our business, such as seven Cows storage, SMS and mail, or some business switches.

However, with the continuous iteration of the microservice system, the whole microservice system may become a “network structure”. At this time, the “expansibility, scalability, coupling” and so on of the whole microservice system should be considered. One of the most important aspects is the issue of configuration management.

Disadvantages of conventional configuration management solutions

  • Hard coding (code modification, tedious, risky)
  • Properties or YML (replacement and restart required in clustered environments)
  • XML (repackage and restart)

Why use Spring Cloud Config


Because of the drawbacks of conventional configuration management, Spring Cloud Config uses a “centralized” configuration center to manage configuration information for “per service.”

In microservice distributed system, Spring Cloud Config adopts the mode of “Server side” and “Client side” to provide extensible configuration services. The server stores the configuration file and provides the content of the configuration file through interfaces. The client obtains data through the interface and initializes its own application based on this data.

The configuration center is responsible for the various environment profiles for “Manage All services”.

By default, the configuration center uses Git to store configuration files, so it can be easily deployed and modified to facilitate version management of the environment configuration.

What problem does Spring Cloud Config solve

Spring Cloud Config solves the problems of “centralization, version control, platform independence, and language independence” in microservice configuration. Its characteristics are as follows:

  • Provide Server and Client support (Spring Cloud Config Server and Spring Cloud Config Client)
  • Centrally manage application deployment in a distributed environment
  • Encryption and decryption of attribute values (symmetric and asymmetric encryption)
  • Seamlessly integrates with Spring applications based on the Spring environment
  • Programs that can be developed in any language
  • The default implementation is based on Git and can be versioned

Next, we will talk about the use of Config mainly from the following blocks.

  1. Base configuration center (not integrated with Eureka)
  2. High availability configuration center integrated with Eureka version
  3. The configuration can be automatically refreshed based on the Actuator
  4. Configure encryption and decryption of central attribute values (symmetric and asymmetric encryption)
  5. Automatic refresh of configuration based on Spring Cloud Bus
  6. Configure security authentication for central users

Environment to prepare

project

Config-demo Aggregation project. SpringBoot 2.2.4.RELEASE, Spring Cloud hoxton.sr1

  • eureka-server: registry (configuration center for integration with Eureka version)
  • eureka-server02: registry (configuration center for integration with Eureka version)
  • order-service: Order service (configuration center for integration with Eureka edition)

warehouse

The config – ‘warehouse.


  • Repository name: Name of warehouse
  • The Description (optional): Warehouse description
  • Public and Private: Warehouse permissions (publicly shared, private or designated partner)
  • Initialize this repository with a README: Add a readme.md
  • Add .gitignore: Indicates the file type that does not need version management.gitignore
  • Add a license: indicates the certificate type. The corresponding file is generatedLICENSE

The configuration file

Configuration files for different environments are uploaded to the config-repo repository.


For example, config-client-dev.yml and config-client-prod.yml are two different environments of the same project. The project name is config-client, one of which corresponds to the development environment and the other to the formal environment. Test Indicates the test environment.

config-client.yml

server:
  port: 7777 # port

spring:
 application:
 name: config-client # app name  # Custom configuration name: config-client-default Copy the code

config-client-dev.yml

server:
  port: 7778 # port

spring:
 application:
 name: config-client # app name  # Custom configuration name: config-client-dev Copy the code

config-client-test.yml

server:
  port: 7779 # port

spring:
 application:
 name: config-client # app name  # Custom configuration name: config-client-test Copy the code

config-client-prod.yml

server:
  port: 7780 # port

spring:
 application:
 name: config-client # app name  # Custom configuration name: config-client-prod Copy the code

An introduction to case

Basic Configuration Center (without Eureka integration)

The official document: https://cloud.spring.io/spring-cloud-static/spring-cloud-config/2.2.2.RELEASE/reference/html/

Creating a Server

Click the link to watch: Config introduction case to create a server video (for more information, please follow the public account “Mr. Hello Ward”)

Create a child project config-server under the config-demo parent project.

Add the dependent

Add the spring-cloud-config-server dependency. The complete POP.xml file is as follows:


      

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>  <artifactId>config-server</artifactId>  <version>1.0 the SNAPSHOT</version>   <! -- Inheriting parent dependencies -->  <parent>  <groupId>com.example</groupId>  <artifactId>config-demo</artifactId>  <version>1.0 the SNAPSHOT</version>  </parent>   <! -- Project dependencies -->  <dependencies>  <! -- Spring Cloud Config Server -->  <dependency>  <groupId>org.springframework.cloud</groupId>  <artifactId>spring-cloud-config-server</artifactId>  </dependency>   <! -- Spring Boot test dependency -->  <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-test</artifactId>  <scope>test</scope>  <exclusions>  <exclusion>  <groupId>org.junit.vintage</groupId>  <artifactId>junit-vintage-engine</artifactId>  </exclusion>  </exclusions>  </dependency>  </dependencies>  </project> Copy the code

The configuration file

server:
  port: 8888 # port

spring:
 application:
 name: config-server # app name  cloud:  config:  server:  git:  uri: https://github.com/imrhelloworld/config-repo The configuration file is stored in the repository  #username: # Github login account  #password: # Github login password  #default-label: master configuration file branch  Paths: # root directory where the configuration file resides Copy the code

Start the class

The startup class adds the @enableconFigServer annotation.

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
 // Configure central server annotations @EnableConfigServer @SpringBootApplication public class ConfigServerApplication {   public static void main(String[] args) {  SpringApplication.run(ConfigServerApplication.class, args);  }  } Copy the code

Access rules

Spring Cloud Config has a set of access rules that can be accessed directly from the browser.

/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
Copy the code
  • {application}: Application name (target service name)
  • {profile}: Obtain the specified environment configuration, including development environment, test environment, and production environment. The corresponding configuration file is distinguished by application-{profile}.yml. For example, application-dev.yml, application-test.yml, and application-prod.yml. The default value is default.
  • {label}Git: represents the git branch. The default git branch is the master branch. If the project is separated by a branch, you can use different labels to control access to different configuration files.

test

http://localhost:8888/config-client/default

http://localhost:8888/config-client/dev/master

http://localhost:8888/config-client-test.yml

http://localhost:8888/master/config-client-prod.yml

If data can be returned from the preceding addresses, the configuration center server is running properly.

Creating a Client

Click the link to watch: Config introduction case to create client video (for more information, please follow the public account “Mr. Hello Ward”)

Create a child project config-client under the parent project config-demo.

Add the dependent

Add the spring-cloud-starter-config dependency. The complete POm. XML file is as follows:


      

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>  <artifactId>config-client</artifactId>  <version>1.0 the SNAPSHOT</version>   <! -- Inheriting parent dependencies -->  <parent>  <groupId>com.example</groupId>  <artifactId>config-demo</artifactId>  <version>1.0 the SNAPSHOT</version>  </parent>   <! -- Project dependencies -->  <dependencies>  <! -- Spring Cloud Starter Config dependency -->  <dependency>  <groupId>org.springframework.cloud</groupId>  <artifactId>spring-cloud-starter-config</artifactId>  </dependency>  <! Spring Boot Web dependency -->  <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-web</artifactId>  </dependency>   <! -- Spring Boot test dependency -->  <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-test</artifactId>  <scope>test</scope>  <exclusions>  <exclusion>  <groupId>org.junit.vintage</groupId>  <artifactId>junit-vintage-engine</artifactId>  </exclusion>  </exclusions>  </dependency>  </dependencies>  </project> Copy the code

The configuration file

The client configuration file name must be bootstrap.yml

spring:
  cloud:
    config:
      name: config-client Git repository configuration file name, corresponding to the first half of the configuration file
 uri: http://localhost:8888 # config-server Specifies the server address
 label: master # git branch  profile: default # specify environment Copy the code

Control layer

Add a RestController to test to get configuration file information.

package com.example.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
 @RestController public class ConfigController {   @Value("${name}")  private String name;   @GetMapping("/name")  public String getName(a) {  return name;  }  } Copy the code

Start the class

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication public class ConfigClientApplication {   public static void main(String[] args) {  SpringApplication.run(ConfigClientApplication.class, args);  }  } Copy the code

test

Visit: http://localhost:7777/name the results are as follows:


Change the configuration file to dev environment:

spring:
  cloud:
    config:
      name: config-client The first half of the git repository configuration file
 uri: http://localhost:8888 # config-server Specifies the server address
 label: master # git branch  profile: dev # specify environment Copy the code

Visit: http://localhost:7778/name the results are as follows:


Spring Cloud Config is highly available

If Eureka is used as the service registration discovery center in our project, Spring Cloud Config should also be registered with Eureka to facilitate the use of other services. In addition, multiple configuration center servers can be registered to achieve high availability.

Next, integrate Spring Cloud Config into Eureka. For more information about Eureka, check out my historical articles.

Adding a Configuration File

Add a configuration file to the Github repository.


order-service-dev.yml

server:
  port: 9090 # port

spring:
 application:
 name: order-service # app name  Configure the Eureka Server registry eureka:  instance:  prefer-ip-address: true Whether to register with an IP address  instance-id: ${spring.cloud.client.ip-address}:${server.port} # ip:port  client:  service-url: Set service registry address  defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/  # Custom configuration name: order-service-dev Copy the code

order-service-prod.yml

server:
  port: 9091 # port

spring:
 application:
 name: order-service # app name  Configure the Eureka Server registry eureka:  instance:  prefer-ip-address: true Whether to register with an IP address  instance-id: ${spring.cloud.client.ip-address}:${server.port} # ip:port  client:  service-url: Set service registry address  defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/  # Custom configuration name: order-service-prod Copy the code

Integrated Registry

The case is ready for you to use without creating a registry. For clarity, the dependency and configuration information is posted to you.

Rely on

The core dependencies of Eureka-Server and Eureka-Server02 are the same.


      

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>  <artifactId>eureka-server</artifactId>  <version>1.0 the SNAPSHOT</version>   <! -- Inheriting parent dependencies -->  <parent>  <groupId>com.example</groupId>  <artifactId>config-demo</artifactId>  <version>1.0 the SNAPSHOT</version>  </parent>   <! -- Project dependencies -->  <dependencies>  <! -- Netflix Eureka Server dependencies -->  <dependency>  <groupId>org.springframework.cloud</groupId>  <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>  </dependency>  <! Spring Boot Web dependency -->  <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-web</artifactId>  </dependency>   <! -- Spring Boot test dependency -->  <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-test</artifactId>  <scope>test</scope>  <exclusions>  <exclusion>  <groupId>org.junit.vintage</groupId>  <artifactId>junit-vintage-engine</artifactId>  </exclusion>  </exclusions>  </dependency>  </dependencies>  </project> Copy the code

The configuration file

Eureka – server application. Yml

server:
  port: 8761 # port

spring:
 application:
 name: eureka-server # Application name (same under cluster)  Configure the Eureka Server registry eureka:  instance:  hostname: eureka01 If the host name is not specified, the host name will be obtained based on the OS host name  prefer-ip-address: true Whether to register with an IP address  instance-id: ${spring.cloud.client.ip-address}:${server.port} # ip:port  client:  Set service registry address to point to another registry  service-url: The registered address exposed by the registry  defaultZone: http://localhost:8762/eureka/ Copy the code

Eureka – server02 application. Yml

server:
  port: 8762 # port

spring:
 application:
 name: eureka-server # Application name (same under cluster)  Configure the Eureka Server registry eureka:  instance:  hostname: eureka02 If the host name is not specified, the host name will be obtained based on the OS host name  prefer-ip-address: true Whether to register with an IP address  instance-id: ${spring.cloud.client.ip-address}:${server.port} # ip:port  client:  Set service registry address to point to another registry  service-url: The registered address exposed by the registry  defaultZone: http://localhost:8761/eureka/ Copy the code

Start the class

The eureka-Server and Eureka-Server02 startup classes have the same core code.

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
 @SpringBootApplication // Enable EurekaServer annotations @EnableEurekaServer public class EurekaServerApplication {   public static void main(String[] args) {  SpringApplication.run(EurekaServerApplication.class, args);  }  } Copy the code

Spring Cloud Config server

The server has more Eureka configuration than the base configuration center, but everything else is the same.

After the construction of the config-server server is completed, a config-server02 server is copied to achieve high availability.

Rely on

Config-server and config-server02 have the same core dependencies. Note the spring-cloud-config-server dependency.


      

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>  <artifactId>config-server</artifactId>  <version>1.0 the SNAPSHOT</version>   <! -- Inheriting parent dependencies -->  <parent>  <groupId>com.example</groupId>  <artifactId>config-demo</artifactId>  <version>1.0 the SNAPSHOT</version>  </parent>   <! -- Project dependencies -->  <dependencies>  <! -- Spring Cloud Config Server -->  <dependency>  <groupId>org.springframework.cloud</groupId>  <artifactId>spring-cloud-config-server</artifactId>  </dependency>  <! -- Netflix eureka client -->  <dependency>  <groupId>org.springframework.cloud</groupId>  <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>  </dependency>   <! -- Spring Boot test dependency -->  <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-test</artifactId>  <scope>test</scope>  <exclusions>  <exclusion>  <groupId>org.junit.vintage</groupId>  <artifactId>junit-vintage-engine</artifactId>  </exclusion>  </exclusions>  </dependency>  </dependencies>  </project> Copy the code

The configuration file

The config – server application. Yml

server:
  port: 8888 # port

spring:
 application:
 name: config-server # app name  cloud:  config:  server:  git:  uri: https://github.com/imrhelloworld/config-repo The configuration file is stored in the repository  #username: # Github login account  #password: # Github login password  #default-label: master configuration file branch  Paths: # root directory where the configuration file resides  Configure the Eureka Server registry eureka:  instance:  prefer-ip-address: true Whether to register with an IP address  instance-id: ${spring.cloud.client.ip-address}:${server.port} # ip:port  client:  service-url: Set service registry address  defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/ Copy the code

The config – server02 application. Yml

server:
  port: 8889 # port

spring:
 application:
 name: config-server # app name  cloud:  config:  server:  git:  uri: https://github.com/imrhelloworld/config-repo The configuration file is stored in the repository  #username: # Github login account  #password: # Github login password  #default-label: master configuration file branch  Paths: # root directory where the configuration file resides  Configure the Eureka Server registry eureka:  instance:  prefer-ip-address: true Whether to register with an IP address  instance-id: ${spring.cloud.client.ip-address}:${server.port} # ip:port  client:  service-url: Set service registry address  defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/ Copy the code

Start the class

The config-server and config-server02 startup classes have the same core code.

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
 // Enable the EurekaClient annotation. This annotation is enabled by default in the current version if the Eureka registry is configured //@EnableEurekaClient // Configure central server annotations @EnableConfigServer @SpringBootApplication public class ConfigServerApplication {   public static void main(String[] args) {  SpringApplication.run(ConfigServerApplication.class, args);  }  } Copy the code

Spring Cloud Config client

After joining Eureka, clients do not need to directly interact with the configuration center server, but access through Eureka.

Rely on

Order – service of pom. The XML. Note the spring-cloud-starter-config dependency.


      

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>  <artifactId>order-service</artifactId>  <version>1.0 the SNAPSHOT</version>   <! -- Inheriting parent dependencies -->  <parent>  <groupId>com.example</groupId>  <artifactId>config-demo</artifactId>  <version>1.0 the SNAPSHOT</version>  </parent>   <! -- Project dependencies -->  <dependencies>  <! Spring Boot Web dependency -->  <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-web</artifactId>  </dependency>  <! -- Netflix eureka client -->  <dependency>  <groupId>org.springframework.cloud</groupId>  <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>  </dependency>  <! -- Spring Cloud Starter Config dependency -->  <dependency>  <groupId>org.springframework.cloud</groupId>  <artifactId>spring-cloud-starter-config</artifactId>  </dependency>   <! -- Spring Boot test dependency -->  <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-test</artifactId>  <scope>test</scope>  <exclusions>  <exclusion>  <groupId>org.junit.vintage</groupId>  <artifactId>junit-vintage-engine</artifactId>  </exclusion>  </exclusions>  </dependency>  </dependencies>  </project> Copy the code

The configuration file

Order – service of bootstrap. Yml

spring:
  cloud:
    config:
      name: order-service Git repository configuration file name, corresponding to the first half of the configuration file
 label: master # git branch
 profile: dev # specify environment  discovery:  enabled: true # open  service-id: config-server # specify the service id of the configuration center server Copy the code

Control layer

Add a RestController to test to get configuration file information.

package com.example.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
 @RestController public class ConfigController {   @Value("${name}")  private String name;   @GetMapping("/name")  public String getName(a) {  return name;  }  } Copy the code

Start the class

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

// Enable the EurekaClient annotation. This annotation is enabled by default in the current version if the Eureka registry is configured //@EnableEurekaClient @SpringBootApplication public class OrderServiceApplication {   public static void main(String[] args) {  SpringApplication.run(OrderServiceApplication.class, args);  }  } Copy the code

test

Start registries Eureka-Server and Eureka-Server02.

Start config-server on the configuration center server.

Start the order-service on the configuration center client.

The current environment in Eureka UI is as follows:


Visit: http://localhost:9090/name the results are as follows:


Configure the working principle of the center


Developers either store configuration files to a Git remote repository or later modify the files in the Git remote repository. If there is a version change in the remote repository, Config Server synchronizes files from the Git remote repository to the local repository. If you look closely at the Config Server console, you will see information similar to the following.

[nio-8888-exec-1] o.s.c.c.s.e.NativeEnvironmentRepository  : Adding property source: file:/C:/Users/MRHELL~1/AppData/Local/Temp/config-repo-17506367621853740906/order-service-dev.yml
Copy the code

If you open the local directory based on the console information, you will find that the files in the Git remote repository have been synchronized to the local repository.


Why do you do that? Because we have to consider the network fluctuation, the remote warehouse can not access the problem.

In the next article, we will explain how to implement automatic configuration center refresh

This article is licensed under a Creative Commons attribution – Noncommercial – No Deductive 4.0 International license.

You can see more articles about Spring Cloud in the category.

  

🤗 your likes and retweets are the biggest support for me.

📢 Scan code pay attention to Mr. Hallward “document + video” each article is equipped with a special video explanation, learning more easily oh ~