springcloud
config distributed configuration center
Overview: configuration problems faced by distributed systems?
Microservice means to split the business in a single application into one sub service. The granularity of each service is relatively small, so there will be a large number of services in the system. Because each service needs the necessary configuration information to run, a centralized and dynamic configuration management facility is essential.
Spring cloud provides ConfigServer to solve this problem. Each of our microservices carries an application.yml and manages hundreds of configuration files
Official website: https://cloud.spring.io/spring-cloud-static/spring-cloud-config/2.2.1.RELEASE/reference/html/
What is config?
SpringCloud Config provides centralized external configuration support for microservices in the microservice architecture. The configuration server provides a centralized external configuration for all environments of different microservice applications.
How do you do it?
SpringCloud Config is divided into two parts: server and client:
-
The server is also called distributed configuration center. It is an independent micro service application, which is used to connect to the configuration server and provide the client with access interfaces such as obtaining configuration information and encrypting / decrypting information
-
The client manages application resources and business-related configuration content through the specified configuration center, and obtains and loads configuration information from the configuration center at startup. The configuration server uses git to store configuration information by default, which is helpful for version management of environment configuration, The GIT client tool can be used to manage and access the configuration content conveniently
What can we do with it?
- Centrally manage profiles
- Different environments have different configurations, dynamic configuration updates, and deployment by environment, such as dev/test/prod/beta/release
- The configuration is dynamically adjusted during operation. It is no longer necessary to write configuration files on each service deployed machine. The service will uniformly pull and configure its own information from the configuration center
- When the configuration changes, the service can sense the configuration changes and apply the new configuration without restarting
- Expose the configuration information in the form of REST interface: post, curl access and refresh
Preconditions
Integrated configuration with Github
Because spring cloud config uses git to store configuration files by default (there are other methods, such as supporting svn and local files, but Git is the most recommended, and http/https access is used)
Create a new Repository named spring cloud config on Github with your own account
Add these:
Create a new git warehouse and clone on the local hard disk
Hands on Combat
Config server configuration and test
Create a new Module cloud-config-center-3344, which is the Cloud configuration center Module cloudConfig Center
Import dependency
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>com.atguigu.springcloud</groupId> <artifactId>cloud-api-commons</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
Related configuration
server: port: 3344 spring: application: name: cloud-config-center cloud: config: server: git: uri: Fill in your own github route search-paths: - springcloud-config label: master eureka: client: service-url: defaultZone: http://localhost:7001/eureka
Main start
@SpringBootApplication @EnableConfigServer public class ConfigCenterMain3344 { public static void main(String[] args) { SpringApplication.run(ConfigCenterMain3344 .class,args); } }
Test whether the configuration content can be obtained from Github through the Config microservice
Start microservice 3344: http://config-3344.com:3344/master/config -dev.yml
Read rule
/{label}/{application}-{profile}.yml (this method is most recommended)
The configuration information is successfully obtained through GitHub with SpringCloud Config
Config client configuration and testing
New module cloud-config-client-3355
rely on
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>com.atguigu.springcloud</groupId> <artifactId>cloud-api-commons</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
Why is bootstrap.yml written like this
applicaiton.ym1 is a user level resource configuration item. bootstrap.ym1 is a system level item with higher priority
I
Spring Cloud will create a "Bootstrap Context" as the parent context of the Application Context of the spring application. During initialization, BootstrapContext 'is responsible for loading configuration properties from external sources and parsing the configuration. The two contexts share an externally obtained Environment '.
The 'bootstrap') attribute has high priority, and by default, they will not be overwritten by the local configuration. Bootstrap context and Application Context have different conventions, so a 'bootstrap.yml' file is added to ensure the separation of bootstrap context and Application Context configurations.
It is very important to change the application.yml file under the Client module to bootstrap.yml,
Because bootstrap.yml is loaded before application.yml. Bootstrap.yml has higher priority than application.yml
server: port: 3355 spring: application: name: config-client cloud: config: label: master name: config profile: dev uri: http://localhost:3344 eureka: client: service-url: defaultZone: http://eureka7001.com:7001/eureka
Main startup class
@SpringBootApplication @EnableEurekaClient public class ConfigClientMain3355 { public static void main(String[] args) { SpringApplication.run( ConfigClientMain3355.class,args); } }
Business class
@RestController public class ConfigClientController { @Value("${config.info}") private String configInfo; @GetMapping("/configInfo") public String getConfigInfo(){ return configInfo; } }
Start the Config configuration center 3344 micro service and conduct self-test
http://config-3344.com:3344/master/config-dev.yml
You can read the configuration file information in the git repository
Start 3355 as a Client to prepare for access
http://localhost:3355/configInfo
Access the configuration information of the configuration center
The client 3355 successfully accesses SpringCloud Config3344 and obtains configuration information through GitHub
Problems come at any time, dynamic refresh of distributed configuration
Scenario: Linux O & M modifies the content of the configuration file on GitHub to make adjustments
- Refresh 3344 and find that the ConfigServer configuration center responds immediately
- Refresh 3355 and find no response from ConfigServer client
- 3355 does not change unless you restart or reload yourself
Does the client need to restart every time the O & M modifies the configuration file?? Nightmare!!!
Dynamic refresh of Config client
Avoid restarting the client micro service 3355 every time the configuration is updated
POM introduces actor monitoring
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
Modify the configuration to expose all the information
server: port: 3355 spring: application: name: config-client cloud: config: label: master name: config profile: dev uri: http://localhost:3344 eureka: client: service-url: defaultZone: http://eureka7001.com:7001/eureka management: endpoints: web: exposure: include: "*"
@RefreshScope business class Controller modification
@RefreshScope @RestController public class ConfigClientController { @Value("${config.info}") private String configInfo; @GetMapping("/configInfo") public String getConfigInfo(){ return configInfo; } }
After configuration, the operation and maintenance personnel need to send a Post request to refresh 3355
- Must be a Post request
- Command line: curl -X POST“ http://localhost:3355/actuator/refresh ”
After the request
You can dynamically refresh the configuration without restarting
- http://localhost:3355/configInfo
- The client 3355 is successfully refreshed to the latest configuration content
- Service restart is avoided
There are still remaining problems
At this time, new problems come again
If there are multiple microservice clients 3355 / 3366 / 3377....
Each microservice needs to execute a post request and refresh manually?
Can we broadcast one notice and take effect everywhere?
We want a wide range of automatic refresh and find methods. If there is a need, someone will solve it
Bus message bus
In a word
- Distributed automatic refresh configuration function
- Spring Cloud Bus can be used with Spring Cloud Config to dynamically refresh the configuration
What is Bus?
What can he do?
Why is it called a bus?
What is a bus:
In microservice architecture systems, lightweight message brokers are usually used to build a common message topic and connect all microservice instances in the system. Since the messages generated in this topic will be monitored and consumed by all instances, it is called message bus. Each instance on the bus can easily broadcast some messages that need to be known by other instances connected to the subject.
Basic principle:
ConfigClient instances listen to the same Topic in MQ (springcloudbus by default). When a service refreshes the data, it will put this information into the Topic, so that other services listening to the same Topic can be notified, and then update their own configuration.
RabbitMQ environment configuration
Install Erlang, download address: http://erlang.org/download/otp_win64_21.3.exe
Install RabbitMQ at: https://dl.bintray.com/rabbitmq/all/rabbitmq-server/3.7.14/rabbitmq-server-3.7.14.exe
Enter the sbin directory under the RabbitMQ installation directory
D:\rabbitmq_server-3.7.14\sbin
Open the command line: rabbitmq plugins enable rabbitmq_ management
After execution, you can see
Visit the address to see if the installation was successful: http://localhost:15672/
Spring cloud bus dynamically refreshes global broadcast
You must have a good RabbitMQ environment first
Demonstrate the broadcast effect, increase the complexity, and then make another 3366 with 3355 as the template
Design idea
-
Use the message bus to trigger a client / bus/refresh and refresh the configuration of all clients
-
Use the message bus to trigger the / bus/refresh endpoint of a server ConfigServer and refresh the configuration of all clients (more recommended)
-
The architecture in Figure 2 is obviously more suitable, and the reasons why Figure 1 is not suitable are as follows
- It breaks the single responsibility of microservices, because microservices are business modules, which should not bear the responsibility of configuration refresh
- It destroys the peer-to-peer of micro service nodes
- There are certain limitations. For example, when a microservice is migrated, its network address often changes. At this time, if you want to refresh automatically, you will add more modifications
Add message bus support to cloud-config-center-3344 configuration center server
pom
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-amqp</artifactId> </dependency>
Update profile
server: port: 3344 spring: application: name: cloud-config-center cloud: config: server: git: uri: https://github.com/hhf19906/springcloud-config.git #git@github.com:hhf19906/springcloud-config.git search-paths: - springcloud-config label: master rabbitmq: host: localhost port: 5672 username: guest password: guest eureka: client: service-url: defaultZone: http://localhost:7001/eureka management: endpoints: web: exposure: include: 'bus-refresh'
Add message bus support to cloud-config-center-3355 client
pom
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-amqp</artifactId> </dependency>
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-amqp</artifactId> </dependency>
to configure
server: port: 3355 spring: application: name: config-client cloud: config: label: master name: config profile: dev uri: http://localhost:3344 rabbitmq: host: localhost port: 5672 username: guest password: guest eureka: client: service-url: defaultZone: http://eureka7001.com:7001/eureka management: endpoints: web: exposure: include: "*"
3366 and 3355 follow suit
test
Modify the configuration file on Github and increase the version number
Send Post request
curl -X POST "http://localhost:3344/actuator/bus-refresh"
Send once, take effect everywhere
View the configuration center
http://config-3344.com/config-dev.yml
View client
http://localhost:3355/configInfo
http://localhost:3366/configInfo
Get the configuration information and find that it has been refreshed. Once modified, broadcast the notice and take effect everywhere
Spring cloud bus dynamic refresh set specified notification
I don't want to be notified in full, but I just want to be notified at a fixed point
- Notice only 3355
- No notice 3366
Specify a specific instance to take effect instead of all
Formula: http://localhost: Port number of configuration center / Actor / bus refresh / {destination}
/The bus/refresh request is no longer sent to the specific service instance, but to the config server and specifies the service or instance to update the configuration through the destination parameter class
After sending, you will find
Only 3355 have been updated
3366 not updated
Global notification flowchart
- The request goes to the configserver first, and tells the configuration to be refreshed and whether to notify at a fixed point
- config server pulls the corresponding configuration from git
- Send a message to the message bus,
- The message bus sends messages and the client receives them