Spring Cloud Config可用于统一管理微服务配置
一、Spring Cloud Config简介
Spring Cloud Config为分布式系统外部化配置提供了服务器端和客户端的支持,它包括了Config Server和Config Client两部分。
因为Config Server和Config Client都实现了对Spring Environment和PropertySource抽象的映射,因此,Spring Cloud Config非常适合Spring应用程序,当然也可以和其他语言的应用程序配合。
Config Server是一个可横向扩展、集中式的配置服务器,它用于集中管理应用程序各个环境下的配置,默认使用Git存储配置内容,因此可很方便的实现对配置的版本控制与内容审计
Config Client是Config Server的客户端,用于操作存储在Config Server中的配置属性。
二、编写Config Server
2.1 在git仓库https://git.oschina.net/itmuch/spring-cloud-config-repo中新建几个配置文件:
microservice-foo.properties
microservice-foo-dev.properties
microservice-foo-test.properties
microservice-foo-production.properties
内容分别为:
profile=default-1.0
profile=dev-1.0
profile=test-1.0
profile=production-1.0
2.2 添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
<version>1.2.2.RELEASE</version>
</dependency>
2.3 启动类上加@EnableConfigServer注解
2.4 编写配置文件
server.port=8080
spring.application.name=config-server
spring.cloud.config.server.git.uri=https://git.oschina.net/itmuch/spring-cloud-config-repo
spring.cloud.config.server.git.username=guest
spring.cloud.config.server.git.password=guest
2.5 使用Config Server的端点获取配置文件的内容
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
按照此规则,本例可使用以下URL访问到Git仓库master分支的microservice-foo-dev.properties:
http://localhost:8080/microservice-foo/dev
http://localhost:8080/microservice-foo-dev.properties
http://localhost:8080/microservice-foo-dev.yml
三、编写Config Server
3.1 添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
3.2 创建启动类,正常就行,无需其他注解
3.3 配置文件
server.port=8081
3.4 配置bootstrap.xml,不是application.xml,注意了
spring.application.name=microservice-foo #对应config server所获取的配置文件中的{application}
spring.cloud.config.uri=http://localhost:8080/ #指定config server地址,默认http://localhost:8888
spring.cloud.config.profile=dev #对应config server所获取的配置文件中的{profile}
spring.cloud.config.label=master #指定Git仓库的分支,对应config server所获取的配置文件的{label}
注:Spring Cloud有一个“引导上下文”的概念,这是主应用程序的父上下文。引导上下文负责从配置服务器加载配置属性,以及解密外部配置文件中的属性。和主应用程序加载application.xml中的属性不同,引导上下文加载bootstrap.xml中的属性。配置在bootstrap.xml中的属性有更高的优先级,因此默认情况下它们不能被本地配置覆盖。
3.5 编写controller
@RestController
public class ConfigClientController {
@Value("${profile}")
private String profile;
@GetMapping("/profile")
public String hello(){
return this.profile;
}
}
四、Config Server的Git仓库配置详解
4.1 占位符支持
Config Server的占位符支持{application}、{profile}、{label}
spring.application.name=config-server
spring.cloud.config.server.git.uri=https://git.oschina.net/itmuch/{application}
spring.cloud.config.server.git.username=guest
spring.cloud.config.server.git.password=guest
4.2 模式匹配
模式匹配:带有通配符的{application}/{profile}名称的列表。如果{application}/{profile}不匹配任何模式,它将使用spring.cloud.server.git.uri定义的URI
spring.cloud.config.server.git.uri=https://github.com/spring-cloud-samples/config-repo
spring.cloud.config.server.git.repos.simple=https://github.com/simple/config-repo
spring.cloud.config.server.git.repos.special.pattern=special*/dev*,*special*/dev*
spring.cloud.config.server.git.repos.special.uri=http://github.com/special/config-repo
spring.cloud.config.server.git.repos.local.pattern=local*
spring.cloud.config.server.git.repos.local.uri=file:/home/configsvc/config-repo
4.3 搜索目录
很多时候可能把配置文件放在了Git仓库子目录中,可用search-path指定。search-path同样支持占位符。
spring.cloud.config.server.git.uri=https://git.oschina.net/itmuch/spring-cloud-config-repo
spring.cloud.config.server.git.search-path=foo,bar*
4.4 启动时加载配置文件
默认情况下,在配置首次请求时,Config Server才会clone Git仓库。也可以让Config Server在启动的时候就去clone Git仓库
spring.cloud.config.server.git.uri=https://github.com/spring-cloud-samples/config-repo
spring.cloud.config.server.git.repos.pattern=microservice-*
spring.cloud.config.server.git.repos.clone-on-start=true
spring.cloud.config.server.git.repos.uri=https://git.oschina.net/itmuch/spring-cloud-config-repo
也可以进行全局配置(可帮助Config Server启动时快速识别错误的配置源):
spring.cloud.config.server.git.clone-on-start=true
4.5 打印Config Server请求Git仓库的细节
logging.level.org.springframework.cloud=DEBUG
logging.level.org.springframework.boot=DEBUG
五、Config Server的健康状况指示器
5.1 Config Server自带了一个健康状况指示器,用于检查所配置的EnvironmentRepository是否可以正常工作。可使用/health端点查询当前健康状态。默认情况下,健康指示器向EnvironmentRepository请求的{application}是app,{profile}和{label}是对应EnvironmentRepository实现的默认值。对于Git,{profile}是default,{label}是master。
server.port=8080
spring.application.name=config-server
spring.cloud.config.server.git.uri=https://github.com/spring-cloud-samples/config-repo/
spring.cloud.config.server.git.username=guest
spring.cloud.config.server.git.password=guest
spring.cloud.config.server.health.repositories.a-foo.label=config-label-v2.0
spring.cloud.config.server.health.repositories.a-foo.name=microservice-foo
spring.cloud.config.server.health.repositories.a-foo.profiles=dev
5.2 禁用健康状况指示器
spring.cloud.config.server.health.enabled=false
六、配置内容的加解密
6.1 安装JCE
Java8JCE地址:http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
6.2 Config Server的加解密端点
加密端点:/encrypt
解密端点:/decrypt
加密明文:
curl $CONFIG_SERVER_URL/encrypt -d 想加密的明文
解密密文:
curl $CONFIG_SERVER_URL/decrypt -d 想解密的密文
6.3 对称加密
6.3.1 创建bootstrap.xml,记住配置文件不要写错了
encrypt.key=foo #对称加密秘钥
6.4 存储加密的内容
加密后的内容可用{cipher}密文的形式存储
6.4.1 创建配置文件encryption.xml
spring.datasource.username=dbuser
spring.datasource.password={cipher}djfafjqo2323kwef
并将其push到Git仓库(https://git.oschina.net/itmuch/spring-cloud-config-repo)。
注:如果用的yml的话,password里面的内容一定要用单引号引起来
6.4.2 使用http://localhost:8080/encrption-default.xml
6.5 非对称加密
6.5.1 创建一个Key Store
keytool -genkeypair -alias mytestkey -keyalg RSA -dname "CN=Web Server,OU=Unit,O=Organization,L=City,S=State,C=US" -keypass changeme -keystore server.jks -storepass letmein
6.5.2 将生成的server.jks文件复制到项目的classpath下
6.5.3 创建bootstrap.xml
encrypt.keyStore.location=classpath:/server.jks #jks文件的路径
encrypt.keyStore.password=letmein #storepass
encrypt.keyStore.alias=mytestkey #alias
encrypt.keyStore.secret=changeme #keypass
curl http://localhost:8080/encrypt -d mysecret
七、使用/refresh端点手动刷新配置
7.1 添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
7.2 修改Controller,添加@RefreshScope注解
@RestController
@RefreshScope
public class ConfigClientController {
@Value("${profile}")
private String profile;
@GetMapping("/profile")
public String hello(){
return this.profile;
}
}
八、使用Spring Cloud Bus自动刷新配置
8.1 Spring Cloud Bus简介
如果所有的微服务节点的配置都需要手动刷新,肯定不行。因此很有必要实现自动刷新。
Spring Cloud Bus使用轻量级的消息代理连接分布式系统的节点,这样可以广播传播状态的更改或者其他的管理指令。可以将Spring Cloud Bus想象成一个分布式的Spring Boot Actuator。
8.2 实现自动刷新
8.2.1 添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
<version>1.1.0.RELEASE</version>
</dependency>
8.2.2 bootstrap1.xml添加配置
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
8.3 局部刷新
使用/bus/refresh端点的destination参数来定位要刷新的应用程序
/bus/refresh?destination=customers:9000
其中,destination参数也可以用来定位特定的微服务,用来触发customers微服务所有实例的配置刷新
/bus/refresh?destination=customers:**
8.4 架构改进
最开始的架构图:
改进后的架构图:
8.5 跟踪总线事件
如果想知道Spring Cloud Bus事件传播的细节,可以跟踪总线事件
spring.cloud.trace.enabled=true
在/bus/refresh端点被请求后,访问/trace端点即可
8.6 Spring Cloud Config与Eureka配合使用
8.6.1 将Config Server和Config Client都注册到Eureka Server
8.6.2 Config Client的bootstrap.xml
spring.application.name=microservice-foo #对应config server所获取的配置文件中的{application}
spring.cloud.config.profile=dev #对应config server所获取的配置文件中的{profile}
spring.cloud.config.label=master #指定Git仓库的分支,对应config server所获取的配置文件的{label}
spring.cloud.config.discovery.enable=true #表示使用服务发现组件中的Config Server,而不自己指定Config Server的uri,默认false
spring.cloud.config.discovery.service-id=microservice-config-server-eureka #指定ConfigServer在服务发现中的serviceId,默认是configserver
8.7 Spring Cloud Config的用户认证
8.7.1 添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.1.6.RELEASE</version>
</dependency>
8.7.2 在application.xml中添加
security.basic.enabled=true #开启基于HTTP Basic的认证
security.user.name=user #配置账号
security.user.password=123 #配置密码
8.7.3 Config Server有两种方法使用需用户认证的Config Server
方法一:
spring.cloud.config.uri=http://user:123@localhost:8080/
方法二:
spring.cloud.config.uri=http://localhost:8080/
spring.cloud.config.username=user
spring.cloud.config.password=123
注:方法二的优先级高于方法一,会覆盖方法一的账号和密码
九、Config Server的高可用
9.1 Git仓库的高可用
方法一:
使用第三方Git仓库
方法二:
自建Git仓库管理系统
9.2 RabbitMQ高可用:见我MQ里面的详解
9.3 Config Server高可用
9.3.1 Config Server未注册到Eureka Server上
Config Server可借助一个负载均衡器实现
9.3.2 Config Server已注册到Eureka Server上
将Config Server节点注册到Eureka Server即可