本文接着上一篇文章:实践讲解Spring配置中心confighttps://blog.csdn.net/Xin_101/article/details/127584130,实现配置中心文件刷新后自动同步到其他服务,
保证了连接到配置中心的服务实时获取最新的配置文件,
同样,以图文的方式讲解工程实现,
实现原理会在后续的文章中讲解。
Spring配置中心Config自动同步配置文件的架构及实现流程架构如下图所示,
由图可知,Spring配置中心Config使用总线的方式,将变更的消息同步到消息队列Q,
分发到其他服务监听消息队列(Q1,Q2,…,Qn),
其他服务将消息加载到各自的内存中。
连接到配置中心的其他服务,会在各自的服务中创建并监听对应的队列(Q1,Q2,…,Qn),
这样,其他服务的数据会同步更新。
服务启动后,注册中心监控面板如下图所示,
由图可知,有两个服务:CONFIG和COMMON两个服务注册到Eureka,
其中,CONFIG为Spring配置中心,COMMON为测试的服务。
Spring配置中心和测试的一个服务启动后,会各自创建并监听对应的队列,
RabbitMQ的监控的队列如下图所示,
由图可知,Spring配置中心监听的队列:springCloudBus.anonymous.2s6VCOyFS2iH-KlGKKaz6g
其他服务监听的队列:springCloudBus.anonymous.ZfL2pRe2Q6WWZSoUK5V7mg
自动同步配置文件变更,需要引入总线组件,Spring提供的总线组件:bus-amqp,
很好地解决了配置中心数据变更分发的问题,
连接到SpringConfig的服务可以同步自动获取变更的内容。
新引入的依赖有bus-amqp和actuator,
bus-amqp用于消息传递,actuator用于URL监听,触发消息同步。
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
<version>2.2.3.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-config-serverartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-bus-amqpartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
配置参数中有两点变更&#xff0c;配置如下&#xff1a;
&#xff08;1&#xff09;使用本地路径存储配置文件&#xff0c;用于测试文件变更&#xff08;替换resources&#xff0c;这里服务启动后无法变更&#xff09;&#xff1b;
&#xff08;2&#xff09;暴露触发数据更新的URI&#xff0c;用于触发数据传递&#xff08;通过队列&#xff09;。
spring:
application:
name: config
profiles:
active: native
cloud:
config:
server:
native:
search-locations: file:D:/JProject/spring-config-file
rabbitmq:
host: localhost
port: 5672
username: xindaqi
password: 123456
publisher-confirm-type: correlated
publisher-returns: true
virtualHost: /tutorial
listener:
direct:
acknowledge-mode: manual
simple:
acknowledge-mode: manual
concurrency: 1
max-concurrency: 1
retry:
enabled: true
server:
port: 9002
servlet:
session:
timeout: PT10S
eureka:
client:
fetch-registry: true
register-with-eureka: true
service-url:
defaultZone: http://localhost:8001/eureka/eureka
management: # 暴露监控路径
endpoints:
web:
exposure:
include: bus-refresh
共用的配置文件&#xff1a;D:/JProject/spring-config-file/application-dev.yml&#xff0c;
其中&#xff0c;my.config用于测试文件内容变更。
spring:
devtools:
restart:
enabled: true
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/db_monkey_run?useUnicode&#61;true&characterEncoding&#61;UTF-8&useSSL&#61;false&serverTimezone&#61;Asia/Shanghai
username: root
password: 123456
type: com.alibaba.druid.pool.DruidDataSource
druid:
initial-size: 10
max-active: 100
min-idle: 10
max-wait: 6000
filters: stat, wall
stat-view-servlet:
enabled: true
login-username: admin
login-password: 123456
logging:
level:
root: DEBUG
pagehelper:
helperDialect: mysql
reasonable: true
supportMethodsArguments: true
params: count&#61;countSql
my:
config: xiaohuahua
注意使用&#64;EnableConfigServer开启配置中心。
package com.monkey.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
/**
* 启动类.
*
* &#64;author xindaqi
* &#64;date 2021-04-30 18:22
*/
&#64;SpringBootApplication
&#64;EnableConfigServer
public class ConfigApplication {
private static final Logger logger &#61; LoggerFactory.getLogger(ConfigApplication.class);
public static void main(String[] args) {
SpringApplication.run(ConfigApplication.class, args);
logger.info(">>>>>>>>Config启动成功");
}
}
启动服务时&#xff0c;会监听队列&#xff0c;日志信息如下图所示。
初始文件内容&#xff1a;
my:
config: xiaohuahua
变更后的内容&#xff1a;
my:
config: xiaolanlan
通过刷新接口&#xff0c;将最新数据同步到队列&#xff0c;并触发数据同步。
测试结果如下图所示&#xff0c;
这里&#xff0c;没有响应体&#xff0c;只有响应码&#xff1a;204。
刷新数据时&#xff0c;RabbitMQ中的数据监控如下图所示&#xff0c;
虽然没有在队列中看到数据&#xff0c;但是&#xff0c;通过消息速率&#xff0c;
可知&#xff0c;确实是有数据经过该队列的。
与Spring配置中心一样&#xff0c;需要总线和接口监控组件&#xff0c;
集成bus-amqp和actuator。
依赖如下&#xff1a;
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
<version>2.2.3.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-config-clientartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-bus-amqpartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
直接使用bootstrap.yml&#xff0c;内容如下&#xff1a;
说明&#xff1a;不配置application.yml&#xff0c;因为没有使用config配置中心时&#xff0c;application.yml配置了其他的环境文件&#xff08;application-dev.yml等&#xff09;&#xff0c;
当使用config配置中心的文件测试时&#xff0c;使用公共环境文件替代了项目中的环境文件&#xff08;application-dev.yml等&#xff09;。
spring:
cloud:
config:
discovery:
enabled: true # 开启发现spring-config服务
service-id: config # spring-config服务ID
name: application # spring-config服务中的配置文件前缀
profile: dev # spring-config服务中的配置文件后缀&#xff0c;完整&#xff1a;application-dev.yml
rabbitmq:
host: localhost
port: 5672
username: xindaqi
password: 123456
publisher-confirm-type: correlated
publisher-returns: true
virtualHost: /tutorial
listener:
direct:
acknowledge-mode: manual
simple:
acknowledge-mode: manual
concurrency: 1
max-concurrency: 1
retry:
enabled: true
eureka:
client:
fetch-registry: true
register-with-eureka: true
service-url:
defaultZone: http://localhost:8001/eureka/eureka
management: # 暴露监控路径
endpoints:
web:
exposure:
include: bus-refresh
为测试配置自动刷新&#xff0c;使用&#64;Value读取配置配置my.config&#xff0c;
使用&#64;RefreshScope触发获取变更的数据&#xff0c;样例如下&#xff1a;
package com.monkey.common.api;
import com.monkey.common.common.response.Response;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 配置数据接口.
*
* &#64;author xindaqi
* &#64;since 2022-10-28 17:46
*/
&#64;RestController
&#64;RequestMapping("/api/v1")
&#64;RefreshScope
public class ConfigDataApi {
&#64;Value("${spring.datasource.url}")
String datasourceUrl;
&#64;Value("${my.config}")
String myConfig;
&#64;GetMapping("/datasource/url")
public Response<String> getDatasourceUrl() {
return Response.success(datasourceUrl);
}
&#64;GetMapping("/my-config")
public Response<String> getMyConfig() {
return Response.success(myConfig);
}
}
第一次的读取配置文件结果如下图所示。
当Spring配置中心变更数据时&#xff0c;对应的其他客户端&#xff08;连接到配置中心的服务&#xff09;监听的队列会同步获取到消息&#xff0c;
日志信息如下图所示。
更直观的展示通过RabbitMQ监控面板可以看到&#xff0c;如下图所示&#xff0c;
由图可知&#xff0c;有新的数据入队&#xff0c;并被消费&#xff0c;此时&#xff0c;该服务内存中的配置数据已自动更新。
第二次的读取配置文件结果如下图所示&#xff0c;数据自动更新成功。
&#xff08;1&#xff09;自动同步更新配置中心数据&#xff1a;通过bus-amqp和开放刷新接口实现&#xff1b;
&#xff08;2&#xff09;Spring配置中心和其他连接到配置中心的服务会各自监听一个队列&#xff0c;同步消息&#xff1b;
&#xff08;3&#xff09;在配置中心刷新数据&#xff0c;并通过总线方式&#xff0c;同步消息到其他队列&#xff0c;其他服务通过&#64;RefreshScope更新数据。