前言
本文主要介绍SpringCloud Config组件的应用,以及配合Bus组件实现动态获取server端最新配置。
SpringCloud Config介绍
Spring Cloud Config项目是分布式系统配置管理的解决方案,为分布式系统中的外部配置提供Server和Client,服务端负责读取配置文件,暴露Http API接口,Client通过调用Server的接口来读取配置文件。
Spring Cloud Config 是一种用来动态获取Git、SVN、本地的配置文件等的一种工具,默认使用Git。
准备
JDK:1.8
SpringBoot:2.2.5.RELEASE
SpringCloud:Hoxton.SR3
pom配置:
<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>
</dependencies>
核心配置
Config配置中核心配置:
1.本地配置:spring.profiles.active=native
默认从resources路径下读取,如果需要读取指定目录,使用:
spring.cloud.config.server.native.searchLocations = file:D:/properties/
2.远程配置(Git):
spring.cloud.config.server.git.uri=https://github.com/Jesssssfish/ebusinessDemo/
spring.cloud.config.server.git.search-paths=/config-repo
spring.cloud.config.server.git.username=xxx
spring.cloud.config.server.git.password=xxx
至于username和password,可以不写,据说写了可以提升访问速度,不知真假。
示例
继续在我之前的代码中(SpringCloud学习)引入Spring Cloud Config,学习Config组件。
新建 eb-config-server springboot模块
pom引入
<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>
编写application.yml
spring:
application:
name: eb-config-server
# 配置Git远程地址
cloud:
config:
server:
git:
uri: https://github.com/Jesssssfish/ebusinessDemo/
search-paths: /config-repo
# 配置本地读取
# profiles:
# active: native
server:
port: 8006
# 向eureka中心注册
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8000/eureka/
Springboot启动类上添加注解@EnableConfigServer和@EnableEurekaClient
启动服务注册中心EbEurekaServerApplication。
启动配置中心EbConfigServerApplication。
在eb-order-server订单服务模块添加config-client相关配置。
pom引入:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
</dependency>
新建bootstrap.yml
spring:
cloud:
config:
name: ebConfig
# 本地配置文件名
# name: nativeConfigtest
profile: test
label: master
discovery:
enabled: true
service-id: eb-config-server
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8000/eureka/
spring.cloud.config.profile:获取配置的策略
spring.cloud.config.label:获取配置文件的分支,默认是master。如果是是本地获取的话,则无用
注意:因为bootstrap.yml比application.yml优先加载,所以需要将config-client相关配置写入到bootstrap.yml,还有就是需要把application.yml中的eureka.client.service-url.defaultZone移到bootstrap.yml中,不然订单服务中会读取不到配置。
测试
这里就只测试远程仓库配置,不测试本地配置了。在github仓库上建立一个config-repo 文件夹(https://github.com/Jesssssfish/ebusinessDemo/config-repo),也就是eb-config-server模块的application.yml中配置的cloud.config.server.git.uri和cloud.config.server.git.search-paths。
在config-repo 文件夹中编写两个文件ebConfig-dev.yml和ebConfig-test.yml。
在eb-order-server模块中bootstrap.yml中配置的spring.cloud.config.name就是编写的文件的文件名ebConfig。
注意: :配置文件的名称如果是ebConfig.yml,那程序是获取不到的,因为在配置文件名需要通过-来进行获取,如果配置文件名称没有-,那么添加了-之后,会自动进行匹配搜索。
springcloud config 的URL与配置文件的映射关系如下:
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
上面的url会映射{application}-{profile}.properties对应的配置文件,{label}对应git上不同的分支,默认为master。
eb-config-server端口配置的8006,查看ebConfig配置文件。
在访问过程中,控制台输出
2020-03-30 14:31:20.501 INFO 966 --- [nio-8006-exec-8] o.s.c.c.s.e.NativeEnvironmentRepository : Adding property source: file:/var/folders/6x/096fs35s0r77p6b7tt17f4bw0000gp/T/config-repo-2056496214903074730/config-repo/ebConfig-dev.yml
这条消息说明server端在获取到git仓库文件的时候,会缓存到本地目录下,向client端发送配置信息从本地缓存中读取。
接下来在eb-order-server模块controller里面加入并输出
@Value("${eb.config.test1}")
private String test1;
@Value("${eb.config.test2}")
private String test2;
这里的eb.config.test1和eb.config.test2就是配置文件中的key。
启动订单服务EbOrderServerApplication(端口8004)
查看
这里输出的是test环境下的配置,将bootstrap.yml中的spring.cloud.config.profile改为dev,重启eb-order-server模块。
查看
输出了dev环境下的配置内容。
现在有一个问题,如果把配置内容改了,刷新一下server端
没问题,刷新下client端
这里的值并没有刷新,只有重启client端才能看到最新值,这种显然不能满足我们的需求。
那么这就要引入spring boot actuator执行器,执行刷新。
spring boot actuator,是spring boot项目运行的一个监视器服务,启动项目的endpoints就是由spring boot actuator输出的,包含了对spring boot的bean的监视,健康状况的管理,可以通过/actuator 查看各种项目运行的信息。
eb-order-server pom引入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
controller加上@RefreshScope注解
bootstrap.yml加上
# 刷新范围
management.endpoints.web.exposure.include=*
# 如果是yml,要用"*"
用post方式请求 http://127.0.0.1:8004/actuator/refresh
这时再刷新一下客户端,配置已更改
这样实现了动态刷新,但是又有另一个问题,每次更新文件都需要子服务手动刷新来获取最新值,服务量一旦过大对于维护以及体验都很糟糕。所以这里有引入了Spring Cloud的另一个组件:Spring Cloud Bus。
Spring Cloud Bus
Spring Cloud Config 与 Spring Cloud Bus 搭配实现无需子服务手动刷新即可动态获取服务端最新值。
Spring Cloud Bus支持rabbit以及kafka两种MQ,kafka主要针对大数据,这里我们使用RabbitMQ。
现在有这样一个需求:订单服务系统需要实现高可用,有3个节点,如果配置中心配置更改,要实现每个节点都能获取最新配置。
按照上面的做法,每个节点都需要/actuator/refresh刷新一下配置,显然不可行,系统修改如下:
订单服务pom引入:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
application.yml添加:
# mq的ip地址
spring.rabbitmq.host=127.0.0.1
# mq的端口
spring.rabbitmq.port=5672
# mq的用户密码
spring.rabbitmq.password=guest
# mq的用户名
spring.rabbitmq.username=guest
复制两个订单服务系统并修改端口,三个订单服务系统端口:8004、8007、8008,分别启动这三个系统。
修改配置文件,发送一个post请求(8004\8007\8008随便发一个):http://127.0.0.1:8004/actuator/bus-refresh
可以看到三个订单服务系统获取的配置都是最新值。
总结
本篇文章学习了Spring Cloud Config配置中心的搭建与应用,以及spring boot actuator执行器手动执行进行刷新、配合Spring Cloud Bus实现配置动态刷新。
代码已上传GitHub:https://github.com/Jesssssfish/ebusinessDemo
谢谢。