Catalog
Spring Cloud Config server example
Spring Cloud Config client example
Spring Cloud Config user authentication
Configure information encryption
Spring Cloud Config client sends update notification
Spring Cloud Config server sends update notification
Spring Cloud Config integrates Eureka
Modify the Spring Cloud Config server
Modify the Spring Cloud Config client
Java version: 1.8
Spring version: 5.1.8.RELEASE
Spring Boot version: 2.1.6.RELEASE
Spring Cloud version: Greenwich.SR1
Spring Cloud Config server example
Add spring cloud config server dependency in pom file
<?xml version="1.0" encoding="UTF-8"?> <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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> <relativePath/> </parent> <groupId>com.sean</groupId> <artifactId>config-server</artifactId> <version>0.0.1-SNAPSHOT</version> <name>config-server</name> <description>config-server</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Greenwich.SR1</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
Start the Spring Cloud Config service in the startup class settings
package com.sean; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.config.server.EnableConfigServer; @EnableConfigServer @SpringBootApplication public class ConfigServerApplication { public static void main(String[] args) { SpringApplication.run(ConfigServerApplication.class, args); } }
Log in to your github account, create a config warehouse, and create a test branch for the warehouse. Create the following files under the branch
The configuration content of the Spring Cloud configuration file application.properties is as follows
server.port=8080 spring.application.name=config-server spring.cloud.config.server.git.uri=https://github.com/seanzou88/config spring.cloud.config.server.git.username=****** spring.cloud.config.server.git.password=******
After the program starts, access http://localhost:8080/config-server/online/test (/ {application name} / {profile} [/ {label}], where label represents branch name and master branch is not filled in by default) you can get configuration details
In particular, the URL in this file cannot be accessed directly. It is only used as an identifier
Visit http://localhost:8080/test/config-server-online.properties ([/ {label}] / {application name} - {profile}. Properties, where label represents branch name, and master branch is not filled in by default) get specific environment configuration information
In the Spring Cloud configuration file application.properties, you can also use the fuzzy matching method to set the github library
server.port=8080 spring.application.name=config-server #Default configuration spring.cloud.config.server.git.uri=https://github.com/seanzou88/test #The request path contains config, which will be used spring.cloud.config.server.git.repos.rule1.pattern=*config* spring.cloud.config.server.git.repos.rule1.uri=https://github.com/seanzou88/config #By default, when the request is initiated, the git library will be checked and called #Set the configuration change to true, and the git library configuration will be checked after the project is started spring.cloud.config.server.git.repos.rule1.cloneOnStart=true spring.cloud.config.server.git.username=****** spring.cloud.config.server.git.password=******
Spring Cloud Config client example
<?xml version="1.0" encoding="UTF-8"?> <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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.sean</groupId> <artifactId>config-client</artifactId> <version>0.0.1-SNAPSHOT</version> <name>config-client</name> <description>config-client</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Greenwich.SR1</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
package com.sean; 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); } }
The configuration content of the Spring Cloud configuration file application.properties is as follows
server.port=8081
Spring The configuration content of cloud boot configuration file bootstrap.properties is as follows. The configuration file specifies where to obtain configuration information (the priority of configuration content in the configuration file is higher than application.properties. If you move the following configuration content to application.properties, the configuration will not take effect. The project will use the default configuration of bootstrap.properties to find configuration information
Where http://localhost:8888 is the default address of the Spring Cloud Config server)
spring.application.name=config-server spring.cloud.config.uri=http://localhost:8080 spring.cloud.config.profile=online spring.cloud.config.label=test
The server configuration URL corresponding to this configuration is http://localhost:8080/test/config-server-online.properties
Create a Controller class to verify whether the Spring Cloud Config client can obtain configuration information from the server
package com.sean; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; /** * Created by sean on 2020/2/16. */ @RestController public class Controller { @Value("${env}") private String env; @Value("${desc}") private String desc; @GetMapping("/env") public String getEnv(){ return env; } @GetMapping("/desc") public String getDesc(){ return desc; } }
After project launch, visit http://localhost:8081/env online access http://localhost:8081/desc You can get this is main config file
Spring Cloud Config user authentication
From the previous example, we can see that we can get configuration information from the Spring Cloud Config server by sending http requests, which is undoubtedly very dangerous. If the server address is leaked, it will cause very serious consequences. We can avoid this situation by adding user authentication
Update Spring Cloud Config server code
Modify pom file and add spring boot starter security dependency (form authentication is enabled by default at this time)
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
Modify the Spring Cloud configuration file application.properties and add the following
#If you do not specify a user name and password, the default user name, user, is used and a random password is generated at system startup spring.security.user.name=sean spring.security.user.password=123
Now we visit http://localhost:8080/test/config-server-online.properties , you need to enter the user name and password before you can jump to the target URL
Update Spring Cloud Config client code
Modify the Spring Cloud boot configuration file bootstrap.properties and add the following
spring.cloud.config.username=sean spring.cloud.config.password=123
Configure information encryption
There are some restrictions on JCE provided by JDK. We download unlimited version to replace JCE provided by JDK. Because we use JDK 1.8, the corresponding download address is: http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
After downloading, replace the jar package in the path {JAVA_HOME}/jre/lib/security with the jar package in the compressed package
Symmetric encryption
Modify the Spring Cloud Config server code
Add the Spring Cloud boot configuration file bootstrap.properties, as follows
#Symmetric encryption key encrypt.key=******
Then we use the / encrypt node provided by Spring Cloud Config to encrypt the plaintext
C:\Users\sean>curl http://localhost:8080/encrypt -d online 5d04f58d03844e506659e2160bf063bccea76a0c1cd0c5b77cc5625072c08d30
Let's modify the config-server-online.properties under the test branch of the config project on github, replace the previous clear text with the encrypted content, and add the {cipher} ID before encrypting the content
env={cipher}5d04f58d03844e506659e2160bf063bccea76a0c1cd0c5b77cc5625072c08d30
Visit http://localhost:8080/test/config-server-online.properties , we can find that the encrypted content will be automatically decrypted
Asymmetric encryption
Use the keytool tool provided with JDK to generate the key
C:\Users\sean>D:\Java\jdk1.8.0_121\bin\keytool -genkeypair -alias testkey -keyalg rsa -keystore server.jks
Put the generated server.jks under the Spring Cloud Config server project resource path
Modify the Spring Cloud boot configuration file bootstrap.properties as follows
#Asymmetric encryption key encrypt.key-store.location=classpath:server.jks encrypt.key-store.password=123456 encrypt.key-store.secret=123456 encrypt.key-store.alias=testkey
Then we use the / encrypt node provided by Spring Cloud Config to encrypt the plaintext
C:\Users\sean>curl http://localhost:8080/encrypt -d online AQA6d52vfbCRe9D2hr2XA0Xu9OFxCc586eTp9aLjCL+/7CjBk1RpFn5m5il/p0C1DcKkz6fvwZHopuNLe1Ku33qD43oh+1zSecVu1T0X/ygPza02DfUwaKxCrz0iPuVtvPAXX+02f2+V0Yn+FXW5tGgGRJuAj3witOVwRmChqdjImq8oKCdqtQDOJrCNLziLkIBmLzhnDu14PlKkoVka+zpYqy6d0bKBugfymkuU0V8IOIQZyQacePLgCNy/0qiVI6vb7oTTS4pv4JDkcatnqYxJ9t/k8EoJM4Hp/jOXf0Zj6nD/9hMfzEc8if+02iQiZQnv659QI4t9Gts2Gm2XdFxTwLDOjb/Rc9Q+7KM/OI79G7ZAZpdiBrbWvE2q8eeHJPk=
The remaining steps are the same as symmetric encryption
Configuration refresh
Manual refresh
Modify the pom file of the Spring Cloud Config client and add the spring boot actor dependency
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
Modify the Spring Cloud configuration file application.properties and open the refresh node of the actor
management.endpoints.web.exposure.include=refresh
Add RefreshScope annotation on the controller so that we can manually refresh the configuration information obtained from the server by the Spring Cloud Config client using the refresh node provided by the actor
package com.sean; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; /** * Created by sean on 2020/2/16. */ @RefreshScope @RestController public class Controller { @Value("${env}") private String env; @Value("${desc}") private String desc; @GetMapping("/env") public String getEnv(){ return env; } @GetMapping("/desc") public String getDesc(){ return desc; } }
Then we test. We modify config-server.properties under the test branch of the config project on github, and replace its content with desc=update
Visit http://localhost:8081/desc , the returned result is still this is main config file
Refresh the configuration using the refresh node provided by the actor
C:\Users\sean>curl -v -X POST "http://localhost:8081/actuator/refresh" * Trying ::1... * TCP_NODELAY set * Connected to localhost (::1) port 8081 (#0) > POST /actuator/refresh HTTP/1.1 > Host: localhost:8081 > User-Agent: curl/7.55.1 > Accept: */* > < HTTP/1.1 200 < Content-Type: application/vnd.spring-boot.actuator.v2+json;charset=UTF-8 < Transfer-Encoding: chunked < Date: Mon, 17 Feb 2020 02:54:47 GMT < ["config.client.version","desc"]* Connection #0 to host localhost left intact
The system log is as follows
2020-02-17 10:54:41.385 INFO 11272 --- [nio-8081-exec-4] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$1dd09c4c] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-02-17 10:54:43.011 INFO 11272 --- [nio-8081-exec-4] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at : http://localhost:8080 2020-02-17 10:54:47.309 INFO 11272 --- [nio-8081-exec-4] c.c.c.ConfigServicePropertySourceLocator : Located environment: name=config-server, profiles=[online], label=test, version=1f2955ac5f16256d1a394240c2ad34e45bb6eea6, state=null 2020-02-17 10:54:47.310 INFO 11272 --- [nio-8081-exec-4] b.c.PropertySourceBootstrapConfiguration : Located property source: CompositePropertySource {name='configService', propertySources=[MapPropertySource {name='configClient'}, MapPropertySource {name='https://github.com/seanzou88/config/config-server-online.properties'}, MapPropertySource {name='https://github.com/seanzou88/config/config-server.properties'}]} 2020-02-17 10:54:47.311 INFO 11272 --- [nio-8081-exec-4] o.s.boot.SpringApplication : No active profile set, falling back to default profiles: default 2020-02-17 10:54:47.316 INFO 11272 --- [nio-8081-exec-4] o.s.boot.SpringApplication : Started application in 7.571 seconds (JVM running for 616.389)
Access at this time http://localhost:8081/desc , the returned result changes to update
auto refresh
We need to use Spring Cloud Bus here. Because Spring Cloud Bus only supports RabbitMQ and Kafka, we choose RabbitMQ here
Start the local RabbitMQ service
Spring Cloud Config client sends update notification
Modify the pom file of the Spring Cloud Config client and add the spring cloud starter bus AMQP dependency
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-amqp</artifactId> <version>2.1.2.RELEASE</version> </dependency>
Modify the Spring Cloud boot configuration file bootstrap.properties and add the following
spring.rabbitmq.host=localhost #RabbitMQ default port spring.rabbitmq.port=5672 #RabbitMQ creates account by default spring.rabbitmq.username=guest spring.rabbitmq.password=guest
Modify the Spring Cloud configuration file application.properties and open the bus refresh node of the actor
management.endpoints.web.exposure.include=bus-refresh
Copy the current config client project to create a new project config client1, and change the service port of config client1 to 8082
Then we test. We modify config-server.properties under the test branch of the config project on github, and replace its content with desc=client update
Visit http://localhost:8081/desc and http://localhost:8082/desc , the returned result is still update
Use the bus refresh node provided by the actor to refresh the configuration
C:\Users\sean>curl -v -X POST "http://localhost:8081/actuator/bus-refresh" * Trying ::1... * TCP_NODELAY set * Connected to localhost (::1) port 8081 (#0) > POST /actuator/bus-refresh HTTP/1.1 > Host: localhost:8081 > User-Agent: curl/7.55.1 > Accept: */* > < HTTP/1.1 204 < Date: Wed, 19 Feb 2020 14:59:19 GMT < * Connection #0 to host localhost left intact
Access at this time http://localhost:8081/desc and http://localhost:8082/desc , the returned results are all changed to client update
Then we can add webhook on github's config warehouse to automatically call the bus refresh node of any Spring Cloud Config client to refresh the configuration after each code submission
The overall process of the project is as follows
Spring Cloud Config server sends update notification
Modify the pom file of the Spring Cloud Config server and add the spring cloud starter bus AMQP dependency
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-amqp</artifactId> <version>2.1.2.RELEASE</version> </dependency>
Modify the Spring Cloud boot configuration file bootstrap.properties and add the following
spring.rabbitmq.host=localhost #RabbitMQ default port spring.rabbitmq.port=5672 #RabbitMQ creates account by default spring.rabbitmq.username=guest spring.rabbitmq.password=guest
Modify the Spring Cloud configuration file application.properties and open the bus refresh node of the actor
management.endpoints.web.exposure.include=bus-refresh
Since we have previously enabled user authentication for the Spring Cloud Config server, and the default user authentication method is login authentication, we cannot fill in login authentication in Postman or when we use curl to call the bus refresh node provided by the actor to refresh the configuration, so we need to set Http Basic authentication to be enabled
package com.sean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; /** * Created by sean on 2020/2/28. */ @Configuration public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { //At the same time, it supports login verification or httpbasic verification http.authorizeRequests().anyRequest().authenticated() .and() .formLogin() .and() .httpBasic(); //Turn off cross station request forgery, otherwise the bus refresh node will still report 403 even if the login authentication or http basic authentication passes http.csrf().disable(); } }
Then we carry out a test. We modify the config-server.properties under the test branch of the config project on github, and replace the content with desc=server update
Visit http://localhost:8081/desc , the returned result is still client update
Use the bus refresh node provided by the actor to refresh the configuration
C:\Users\sean>curl -v -X POST "http://sean:123@localhost:8080/actuator/bus-refresh" * Trying ::1... * TCP_NODELAY set * Connected to localhost (::1) port 8080 (#0) * Server auth using Basic with user 'sean' > POST /actuator/bus-refresh HTTP/1.1 > Host: localhost:8080 > Authorization: Basic c2VhbjoxMjM= > User-Agent: curl/7.55.1 > Accept: */* > < HTTP/1.1 204 < Set-Cookie: JSESSIONID=75FF9E8AD7D16955F4FC5E4944FD5DFA; Path=/; HttpOnly < X-Content-Type-Options: nosniff < X-XSS-Protection: 1; mode=block < Cache-Control: no-cache, no-store, max-age=0, must-revalidate < Pragma: no-cache < Expires: 0 < X-Frame-Options: DENY < Date: Thu, 05 Mar 2020 01:51:40 GMT < * Connection #0 to host localhost left intact
Access at this time http://localhost:8081/desc and http://localhost:8082/desc , the returned results are all changed to server update
Similarly, we can add webhook on github's config warehouse to automatically call the Spring Cloud Config server's bus refresh node to refresh the configuration after each code submission
The overall process of the project is as follows
Spring Cloud Config integrates Eureka
In the current configuration, we have specified the Spring Cloud Config server address in the Spring Cloud Config client. When the address changes, we need to modify all the Spring Cloud Config client configurations, so it is necessary to integrate Eureka
Eureka server
Please refer to Eureka of Spring Cloud service discovery Eureka Server in
Modify the Spring Cloud Config server
Add Eureka related dependency in pom
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
Modify the Spring Cloud configuration file application.properties and register it with Eureka
eureka.client.service-url.defaultZone=http://localhost:8000/eureka #Service priority use ip to register to eureka eureka.instance.prefer-ip-address=true # Service renewal task (sending heartbeat) execution interval, default 30s eureka.instance.lease-renewal-interval-in-seconds=10 # Service expiration time, default 90s eureka.instance.lease-expiration-duration-in-seconds=20
Modify the Spring Cloud Config client
Add Eureka related dependency in pom
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
Modify the Spring Cloud boot configuration file bootstrap.properties, remove the previous Spring Cloud Config server address, and use Eureka service discovery instead
#spring.cloud.config.uri=http://localhost:8080 spring.cloud.config.username=sean spring.cloud.config.password=123 eureka.client.service-url.defaultZone=http://sean:123@localhost:8000/eureka spring.cloud.config.discovery.enabled=true spring.cloud.config.discovery.service-id=config-server
Then we test. We modify config-server.properties under the test branch of the config project on github, and replace its content with desc=eureka
Visit http://localhost:8081/desc , the returned result is still server update
Call the bus refresh node of the Spring Cloud Config server to refresh the configuration, and visit again http://localhost:8081/desc , the returned result changes to eureka