Spring Cloud系列—Config配置中心
上篇文章:
Spring Cloud系列—Gateway统一服务入口https://blog.csdn.net/sniper_fandc/article/details/149943145?fromshare=blogdetail&sharetype=blogdetail&sharerId=149943145&sharerefer=PC&sharesource=sniper_fandc&sharefrom=from_link
目录
1 集成Spring Cloud Config
1.1 创建Config Server项目并引入依赖
1.2 开启Spring Cloud Config功能
1.3 创建Git仓库
1.4 为ConfigServer添加配置文件
1.5 向Git仓库提交配置信息
1.6 访问Config Server
1.7 Config Client
1.8 多平台部署配置中心
1.9 配置中心自动刷新
1.10 多平台配置中心自动刷新
2 Spring Cloud Config加密解密
2.1 加密环境检查
2.2 对称加密
2.3 非对称加密
Spring Cloud Config是用于配置集中统一管理的组件,包括Config Server、Config Client和版本控制集成三个部分。
Config Server(配置服务器):负责从后端的各种存储拉取配置信息,并提供REST API给客户端使用。
Config Client(配置客户端):应用程序可以集成Config Client,然后通过Config Client来访问配置服务器(调用相关API),动态地拉取配置信息。
版本控制集成:默认采用Git作为后端存储,利用Git的版本控制功能管理多个版本的配置信息,通过切换版本号可以自动获得对应环境的配置信息。
1 集成Spring Cloud Config
1.1 创建Config Server项目并引入依赖
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-config-server</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
1.2 开启Spring Cloud Config功能
在启动类前添加注解@EnableConfigServer:
@EnableConfigServer@SpringBootApplicationpublic class ConfigServerApplication {public static void main(String[] args) {SpringApplication.run(ConfigServerApplication.class, args);}}
1.3 创建Git仓库
Git仓库用于配置文件的版本管理,ConfigServer会从Git仓库中拉取配置信息给客户端。使用Gitee或Github都可以:
1.4 为ConfigServer添加配置文件
server:port: 7071spring:application:name: config-server # 应用名称cloud:config:server:git:uri: https://gitee.com/superidolsmile/config-server.git #配置文件的Git仓库地址default-label: master #配置文件分支search-paths: config #配置文件所在根目录
1.5 向Git仓库提交配置信息
这部分就是模拟Config的配置管理功能,Config从Git仓库拉取配置信息,因此要先提交一些配置信息用于测试:
config-server-dev.yml文件:
data:env: config-devuser:username: config-devpassword: config-dev
config-server-prod.yml文件:
data:env: config-produser:username: config-prodpassword: config-prod
1.6 访问Config Server
访问规则如下:
1.ip:port/服务名/环境名/[分支、标签或提交ID]
2.ip:port/服务名-环境名.yml
3.ip:port/服务名-环境名.properties
4.ip:port/[分支、标签或提交ID]/服务名-环境名.yml
5.ip:port/[分支、标签或提交ID]/服务名-环境名.properties
其中,[]表示是可选项,不写默认为master分支,常用于版本回滚。服务名对应spring.application.name属性。环境名对应spring.profiles.active属性,比如dev、test和prod等等。简单理解就是Git中的配置文件通常命名就是服务名-环境名.yml或服务名-环境名.properties,因此通过唯一路径就能定位到配置信息。
1.7 Config Client
首先提交Git仓库相关配置信息,这些配置信息是Client启动时需要读取的配置:
product-service-dev.yml文件:
data:env: product-service-dev
product-service-prod.yml文件:
data:env: product-service-prod
在Client中添加依赖,这里选择product-service项目作为客户端,集成Config Client:
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-config</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bootstrap</artifactId></dependency>
Client添加配置信息:
spring:profiles:active: dev #环境为dev开发环境,从ConfigServer拉取的配置文件名为product-service-devapplication:name: product-servicecloud:config:uri: http://127.0.0.1:7071 # 指定配置服务端的地址# profile: dev #同时存在优先生效spring.profiles.active
编写测试接口,观察Client是否能从ConfigServer拉取配置文件:
@RequestMapping("/config")@RestControllerpublic class ConfigController {@Value("${data.env}")private String env;@RequestMapping("/getEnv")public String getEnv(){return "data.env="+ env;}}
1.8 多平台部署配置中心
实际中,配置中心可能存在多个,比如dev环境的配置在一个配置中心,prod环境的配置在另一个配置中,因此为了便于切换读取配置中心的地址,通常在bootstrap.yml文件做如下配置:
spring:profiles:active: dev #环境为dev开发环境,从ConfigServer拉取的配置文件名为product-service-devapplication:name: product-service# cloud:# config:# uri: http://127.0.0.1:7071 # 指定配置服务端的地址# profile: dev #优先生效spring.profiles.active#多平台配置,通过spring.profiles.active设置当前使用的配置中心---spring:config:activate:on-profile: prodcloud:config:uri: http://localhost:7071 #配置中心1---spring:config:activate:on-profile: devcloud:config:uri: http://localhost:7071 #配置中心2(实际两个配置中心的ip和端口号可不同,这里没有多余的机器用于部署两个配置中心)
当spring.profiles.active=dev时,结果如下:
当spring.profiles.active=prod时,结果如下:
1.9 配置中心自动刷新
配置中心默认没有自动刷新功能,即在Git仓库修改配置信息,而Client获取的配置信息是旧版本的。要开启自动刷新,首先要添加监控指标依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency>
接着在Client请求的接口添加@RefreshScope注解,表示自动刷新生效范围:
@RefreshScope@RequestMapping("/config")@RestControllerpublic class ConfigController {@Value("${data.env}")private String env;@RequestMapping("/getEnv")public String getEnv(){return "data.env="+ env;}}
然后在配置文件(application.yml)添加相关端点的配置信息:
#需要开启的端点, 这里主要用到的是refresh端点, 只开启这一个就可以, 为了方便, 可以开启所有端点, 除了shutdown端点management:endpoint:shutdown:enabled: falseendpoints:web:exposure:include: "*"
在访问Client接口前,需要手动刷新(手动调用Post接口http://127.0.0.1:9090/actuator/refresh),主要目的刷新配置信息,否则就仍然不生效。
修改Git仓库的配置信息进行测试:
手动刷新后(如果配置中心无变化,手动刷新是没有任何返回结果的):
注意:这种方式有点类似半自动方式,并且配置中心每发生一次变化,只有手动刷新一次后才能生效。
1.10 多平台配置中心自动刷新
上述自动刷新,如果配置中心有多个不同端口号服务时,由于刷新端点(监控的地址/actuator/refresh)需要指定ip和端口号,因此手动刷新只能对其中一个服务生效,剩下的服务仍然不能生效。
解决办法:Spring Cloud Bus,主要是解决在集群环境中分布式系统的配置变化消息的传播,并且提供事件驱动的通信机制。核心原理是利用消息队列MQ做广播(利用fanout交换机:广播交换机),把所有配置中心都和队列绑定,广播交换机就会把配置修改的消息广播给每个配置中心。Spring Cloud Bus支持两种消息队列:RabbitMQ和Kafka。
因此首先要添加SpringCloudBus依赖:
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bus-amqp</artifactId></dependency>
配置消息队列的URL,比如RabbitMQ(注意也需要开启RabbitMQ服务):
spring:rabbitmq:addresses: amqp://admin:admin@192.168.217.150:5672/testVirtual #依次对应用户名:密码@ip:端口号/虚拟机(MQ中的虚拟机)
然后访问http://localhost:9090/actuator/busrefresh(post请求)就可以实现多平台的手动刷新,同时更新所有配置中心服务的配置信息。
2 Spring Cloud Config加密解密
由于Git仓库可以开源,如果配置文件中填写重要的信息比如用户名和密码,就可能导致不安全。因此有必要对配置文件中的内容进行加密,常见的加密解密算法分为对称密码算法(加密解密密钥一样)、非对称密码算法(加密解密密钥不一样)和摘要算法(加密后格式长度固定且不可逆):
2.1 加密环境检查
Java提供了一个用于加密解密的包JCE(Java Cryptography Extension),该包提供有限长度的对称加密和非对称加密等功能。
注意:如果需要长度不限的JCE包,就需要从Java官网下载:https://www.oracle.com/java/technologies/javase-jce8-downloads.html,并把下载好的jar包放到Java安装目录下的/jre/lib/security目录中(覆盖)。
要使用加密解密功能,首先需要提供加密解密用的密钥,在Config Server的bootstrap.yml文件添加配置:
encrypt:key: xxxyyy123
由于使用到bootstrap.yml文件,因此需要添加bootstrap的依赖:
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bootstrap</artifactId></dependency>
重启Config Server服务,如果访问Config Server服务的地址+/encrypt/status,结果是OK,则说明加密环境配置正确。
2.2 对称加密
加密和解密的实现在EncryptionController类中,访问ip:端口号/encrypt实现加密,请求body中为text类型的加密内容;访问ip:端口号/decrypt实现解密,请求body中为text类型的解密内容。
配置文件中实现加密,就把加密后的字符串放到配置文件中,注意单引号不能省略,{cipher}表明该值是加密内容,客户端如果拉取了该配置,就会对加密内容进行解密:
data:env: product-service-devpassword: '{cipher}9c17f855af6728b5f28fa8854588717b5a485aecd02b9027c5fdfec06cd804d8'
在Client添加接口来测试解密功能是否可以正常使用:
2.3 非对称加密
非对称加密的公钥和私钥不一样,可以使用Java提供的keytool(Java的数字证书管理工具)工具来生成,keytool将密钥(key)和证书(certificates)存在后缀为keystore的文件。
进入Java目录,在bin目录下的keytool.exe就是该工具。打开cmd,输入如下命令:
keytool -genkeypair -keystore D:/config-server.keystore -alias config-server -keyalg RSA -keypass config -storepass config
-genkeypair:表示生成密钥对。
-keystore:表示存储的keystore文件路径。
-alias:为keystore文件起别名。
-keyalg:表示使用的密码算法。
-keypass:密钥的口令。
-storepass:密钥仓库的口令。
把生成的keystore文件移动到一个合适的位置,添加相关配置(在Config Server配置文件配置):
encrypt:key-store:location: config-server.keystore #keystore文件存储路径alias: config-server #密钥别名password: config #storepass密钥仓库口令secret: config #keypass密钥口令
同对称加密一样,访问127.0.0.1:7071/encrypt进行加密,访问127.0.0.1:7071/decrypt进行解密:
把加密后的内容添加到Client需要拉取的配置文件中,测试是否可以解密成功:
data:env: product-service-devpassword: '{cipher}AQBe72eorihK/3gyc8+MLRyavOhwwhQpzHDrAENC7smJFz+xhWUaB5HcX7KzkKjvIsIugcmcPoejIoLWYmrvyrxadGlhykgrL5e67hj+5PZsIxLblLq3ox8MI1GiDRiMELgUKfAv/Hw8iHEpFWkpgOXNg9VxYiLKT5dvWtDyzU565pEPYB8KRNS9H5RBmgwTIxir54+IuxuKeCzNvCTMk5UCDRAWC9Ijs0Y011VnQpXFSBnCN0WeNnJ75YUVQHJ9xzxW9YDeSQnBZSzsC/C4FZPIXrEHQI/zv3Bc50HsygcR57XkQAuMFNY8LbsrhoIE/JqAPOaGqWnjEAkPht2W8TR25uOZarElZ7GWDxvCj1yWB+j7AfZYd63947p7DT+EYKQ='
下篇文章: