我们选择上一篇文章 Spring Cloud(八):配置中心(服务化与高可用) 版本的示例代码来改造,MQ 我们使用 RabbitMQ 来做示例。
因为用的是 Spring Boot 2.0.1 + Spring Cloud Finchley.RC1,更新较多,坑也比较多,这里就把代码再贴一遍了。
示例代码:GitHub
服务端
POM 配置
在 pom.xml 里添加,这 4 个是必须的
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-bus</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>
配置文件
application.yml 内容如下
spring:
application:
name: config-server
cloud:
config:
server:
git:
uri: https://github.com/zhaoyibo/spring-cloud-study
search-paths: config-repo
bus:
enabled: true
trace:
enabled: true
server:
port: 12000
eureka:
client:
service-url:
defaultZone: http://localhost:7000/eureka/
management:
endpoints:
web:
exposure:
include: bus-refresh
启动类
加 @EnableConfigServer 注解
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
客户端
POM 配置
在 pom.xml 里添加以下依赖,前 5 个是必须的,最后一个 webflux 你可以用 web 来代替
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-bus</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
这里容易漏掉 spring-boot-starter-actuator,如果缺了这个,当对服务端执行 /actuator/bus-refresh 的时候,客户端接收不到信息,Console 里只会显示以下信息(我就是在这儿被困了好久……)
2018-04-19 18:50:05.711 INFO 39762 — [vOu-GI8c8mJtQ-1] o.s.a.r.c.CachingConnectionFactory : Attempting to connect to: [localhost:5672]
2018-04-19 18:50:05.739 INFO 39762 — [vOu-GI8c8mJtQ-1] o.s.a.r.c.CachingConnectionFactory : Created new connection: rabbitConnectionFactory.publisher#2bc15b3b:0/SimpleConnection@14eb0d5e [delegate=amqp://guest@127.0.0.1:5672/, localPort= 60107]
2018-04-19 18:50:05.749 INFO 39762 — [vOu-GI8c8mJtQ-1] o.s.amqp.rabbit.core.RabbitAdmin : Auto-declaring a non-durable, auto-delete, or exclusive Queue (springCloudBus.anonymous.bOoVqQuSQvOu-GI8c8mJtQ) durable:false, auto-delete:true, exclusive:true. It will be redeclared if the broker stops and is restarted while the connection factory is alive, but all messages will be lost.
配置文件
还是分为两个,分别如下
application.yml
spring:
application:
name: config-client
cloud:
bus:
trace:
enabled: true
enabled: true
server:
port: 13000
bootstrap.yml
spring:
cloud:
config:
name: config-client
profile: dev
label: master
discovery:
enabled: true
service-id: config-server
eureka:
client:
service-url:
defaultZone: http://localhost:7000/eureka/
Controller
@RestController
@RefresgScope
public class HelloController {
@Value ("${info.profile:error}")
private String profile;
@GetMapping ("/info")
public Mono<String> hello() {
return Mono.justOrEmpty(profile);
}
}
@RefreshScope 必须加,否则客户端会受到服务端的更新消息,但是更新不了,因为不知道更新哪里的。
至于启动主类,用默认生成的不用改,就不贴了。
测试
分别启动 eureka、config-server 和两个 config-client
打包
./mvnw clean package -Dmaven.test.skip=true
运行两个 client
java -jar target/spring-cloud-config-client-0.0.1-SNAPSHOT.jar --server.port=13000
java -jar target/spring-cloud-config-client-0.0.1-SNAPSHOT.jar --server.port=13001
启动后,RabbitMQ 中会自动创建一个 topic 类型的 Exchange 和两个以 springCloudBus.anonymous. 开头的匿名 Queue

我们访问 http://localhost:13000/info 和 http://localhost:13001/info 返回内容的都是 dev。
将 Git 中的配置信息由 dev 改为 dev bus,并执行
curl -X POST http://localhost:12000/actuator/bus-refresh/
再次访问 http://localhost:13000/info 和 http://localhost:13001/info 这时返回内容就是修改之后的 dev bus 了,说明成功了。
这里我们再想一个问题:如果对客户端使用 /actuator/bus-refresh 会发生什么呢?是只刷新了当前客户端还是刷新全部客户端,还是一个都没刷新呢?欢迎大家加我qq:1038774626探讨技术问题
不如来试一下吧:
首先我们需要把客户端上的 bus-refresh 端点给放出来
management:
endpoints:
web:
exposure:
include: bus-refresh
重启客户端,这时候访问 http://localhost:13000/info 和 http://localhost:13001/info 返回的都是 dev bus。
去 Git 里把配置信息由 dev bus 改为 dev,然后执行
curl -X POST http://localhost:13000/actuator/bus-refresh/
再次访问 http://localhost:13000/info 和 http://localhost:13001/info 发现这时返回的都是 dev 了,说明只要开启 Spring Cloud Bus 后,不管是对 config-server 还是 config-client 执行 /actuator/bus-refresh 都是可以更新配置的。
其它
因为版本问题,以下两部分还未在该版本进行验证。待有时间了试一下。
局部刷新
某些场景下(例如灰度发布),我们可能只想刷新部分微服务的配置,此时可通过 /actuator/bus-refresh/{destination} 端点的 destination 参数来定位要刷新的应用程序。
例如:/actuator/bus-refresh/customers:8000,这样消息总线上的微服务实例就会根据 destination 参数的值来判断是否需要要刷新。其中,customers:8000 指的是各个微服务的 ApplicationContext ID。
destination 参数也可以用来定位特定的微服务。例如:/actuator/bus-refresh/customers:**,这样就可以触发 customers 微服务所有实例的配置刷新。
跟踪总线事件
一些场景下,我们可能希望知道 Spring Cloud Bus 事件传播的细节。此时,我们可以跟踪总线事件(RemoteApplicationEvent 的子类都是总线事件)。
跟踪总线事件非常简单,只需设置 spring.cloud.bus.trace.enabled=true,这样在 /actuator/bus-refresh 端点被请求后,访问 /trace (现在好像是 /actuator/httptrace)端点就可获得 类似如下的结果
"timestamp": 1495851419032,
"info": {
"signal": "spring.cloud.bus.ack",
"type": "RefreshRemoteApplicationEvent",
"id": "c4d374b7-58ea-4928-a312-31984def293b",
"origin": "stores:8002",
"destination": "*:**"
}
},
{
"timestamp": 1495851419033,
"info": {
"signal": "spring.cloud.bus.sent",
"type": "RefreshRemoteApplicationEvent",
"id": "c4d374b7-58ea-4928-a312-31984def293b",
"origin": "spring-cloud-config-client:8001",
"destination": "*:**"
}
},
{
"timestamp": 1495851422175,
"info": {
"signal": "spring.cloud.bus.ack",
"type": "RefreshRemoteApplicationEvent",
"id": "c4d374b7-58ea-4928-a312-31984def293b",
"origin": "customers:8001",
"destination": "*:**"
}
}
这个日志显示了 customers:8001 发出了 RefreshRemoteApplicationEvent 事件,广播给所有的服务,被 customers:9000 和 stores:8081 接受到了。想要对接受到的消息自定义自己的处理方式的话,可以添加 @EventListener 注解的 AckRemoteApplicationEvent 和 SentApplicationEvent 类型到你自己的应用中。或者到 TraceRepository 类中,直接处理数据。
这样,我们就可清晰地知道事件的传播细节。
本文介绍了如何在Spring Boot 2.0.1和Spring Cloud Finchley.RC1环境中,使用RabbitMQ实现Spring Cloud配置中心的更新。通过配置和示例代码展示了配置文件、启动类的设置,以及客户端和服务端的交互过程,包括刷新配置的测试和局部刷新的原理。最后讨论了如何跟踪总线事件以及事件传播的细节。
-b2b2c小程序电子商务&spm=1001.2101.3001.5002&articleId=104658764&d=1&t=3&u=9e79d92502f44f5ea393637540893657)
3958

被折叠的 条评论
为什么被折叠?



