老鸟飞过 , 学习使用,欢迎交流
十三.消息总线实现配置自动刷新-Spring Cloud Bus 1.基本概念 1.1.为什么要自动刷新配置在上一章节我们学习了如何通过Spring Cloud Config统一管理配置文件,但是有一个不美丽的地方就是每次修改了Git仓库中的配置文件我们需要去重启微服务之后配置才会起作用,这样给我们的微服务带来了极大的不方便,本章节我们将学习一个新的组件Spring Cloud Bus,使用它来实现配置的自动刷新。
1.2.什么是消息总线在微服务架构中,为了更方便的向微服务实例广播消息,我们通常会构建一个消息中心,让所有的服务实例都连接上来,而该消息中心所发布的消息都会被微服务实例监听和消费,我们把这种机制叫做消息总线(SpringCloud Bus),在总线上的每个服务实例都可以去广播一些让其他服务知道的消息,消息总线可以为微服务做监控,或实现应用之间的通信,和其他的一些管理工作,目前提供了两种类型的消息队列中间件支持:RabbitMQ与Kafka,本章节讲述使用 RabbitMQ 作为Spring Cloud的消息组件实现微服务配置自动刷新。
1.3.配置动态刷新方案配置中心实现了配置的统一管理,但是如果有很多个微服务实例,当更改配置时,需要重启多个微服务实例,会非常麻烦。SpringCloud Bus 就能让这个过程变得非常简单,当我们Git仓库中的配置更改后,只需要某个微服务实例发送一个POST请求,通过消息组件通知其他微服务实例重新获取配置文件,以达到配置的自动刷新效果。实现原理如下:
上图是一个配置中心动态刷新配置方案流程图,用到的技术有Spring Cloud Config ,Spring Cloud Config Monitor , Spring Cloud Bus , RabbitMQ .他们的工作流程如下
-
当Git仓库内容发生改变,webhook自动触发Post请求到 /monitor 地址,Spring Cloud Config Monitor的目的是提供了对Git webhook的支持
-
Spring Cloud Config配置中心需要集成 Monitor ,配置中心收到/monitor请求,触发配置刷新,向消息总线发送刷新消息
-
微服务(监听了消息总线的所有服务)监听消息总线,并从消息总线收到配置刷新消息
-
微服务收到消息知道了要刷新配置,请求配置中心重新获取配置文件
-
配置中心从码云重新拉取配置文件返回给微服务
在SpringCloud2.0以前的版本配置刷新URL请求的路径是/bus/refresh ,在SpringCloud2.0以后的版本请求的路径是/actuator/bus-refresh , 但是在使用WebHooks发送/actuator/bus-refresh请求时默认会在body加上一串载荷(payload),程序出现json数据解析异常,有方案可以解决但是比较麻烦也没有必要 。
使用SpringCloud2.0提供了Spring Cloud Config Monitor对Git WebHooks支持 ,使用WebHooks访问 /monitor 刷新配置即可。同时我们要使用Monitor需要在配置中心导入依赖spring-cloud-config-monitor
2.配置文件动态刷新实战 2.1.RabbitMQ安装安装otp_win64_20.2.exe(erlang)
- 下载地址:http://erlang.org/download/otp_win64_20.3.exe
- 双击安装
配置erlang的环境变量
安装RabbitMQ
- 下载地址:http://www.rabbitmq.com/download.html (rabbitmq-server-3.7.4.exe)
- 双击安装RabbitMQ
- 安装RabbitMQ的可视化插件 进入RabbitMQ的安装目录的sbin目录,cmd执行
rabbitmq-plugins.bat enable rabbitmq_management
- 启动RabbitMQ 进入RabbitMQ的安装目录的sbin目录,cmd执行
rabbitmq-service.bat start
- 访问测试 http://127.0.0.1:15672 账号 : guest/guest
配置中心需要集成消息总线bus和RabbitMQ,以及monitor监听/monitor端点实现配置自动刷新
导入依赖 修改配置中心 springcloud-config-server-1070,增加RabbitMQ,Monitor,和Actuator监控依赖
org.springframework.cloud
spring-cloud-starter-bus-amqp
org.springframework.cloud
spring-cloud-config-monitor
org.springframework.boot
spring-boot-starter-actuator
...
修改配置
eureka:
client:
serviceUrl:
defaultZone: http://peer1:1010/eureka/,http://peer2:1011/eureka/,http://peer3:1012/eureka/ #注册中心地址
instance:
prefer-ip-address: true #使用ip地址注册
instance-id: config-server:1070 #指定服务的id
server:
port: 1070
spring:
rabbitmq: #集成RabbitMQ如果配置是默认,可以省略
host: localhost #mq连接地址
port: 5672 #mq端口
username: guest
password: guest
application:
name: config-server
cloud:
config:
server:
git:
#配置远程仓库地址,去仓库中复制
uri: https://gitee.com/little_wolf/springcloud-config-1010.git
username: 1462163787@qq.com #仓库是私有的需要账号
password: 你的密码
#actuator配置
management:
endpoint:
health:
show-details: always #打印日志
endpoints:
web:
exposure:
include: "*" #向外暴露的接口,这里*则表示所有的actuator接口都可以被访问
enabled-by-default: true #开启actuator监控
这里对RabbitMQ做了基础配置,通过management.endpoints.web.exposure.include=“*”暴露了端点,主要是为了/monitor能被访问。
2.3.微服务(客户端)集成消息总线我们这里是集成消息总线做配置配置自动刷新,那么所有的配置中心客户端微服务都需要集成消息总线,都需要做如下操作:如修改springcloud-zuul-server-1060 工程如下
导入依赖 加入bus-amqp基础依赖,为了集成消息总线 ,同时加上服务监控依赖 actuator。
org.springframework.cloud
spring-cloud-starter-bus-amqp
org.springframework.boot
spring-boot-starter-actuator
修改配置
eureka:
client:
serviceUrl:
defaultZone: http://peer1:1010/eureka/,http://peer2:1011/eureka/,http://peer3:1012/eureka/ #注册中心地址
spring:
cloud:
config:
discovery:
enabled: true
service-id: config-server #服务发现的方式执行配置中心
name: application-zuul
profile: dev #环境 组成完整的文件名:application-dept-dev.yml
label: master
bus: #这行代码很重要,根据官方定义的标准来的 ,就是为了产生一个bus.id
id: ${spring.application.name}:${spring.cloud.config.profile}:${random.value}
rabbitmq: #集成RabbitMQ如果配置是默认,可以省略
host: localhost #mq连接地址
port: 5672 #mq端口
username: guest
password: guest
#...省略...
这里配置了 RabbitMQ和Bus ,然后我在码云中的application-zuul-dev.yml中配置了 temp.notify为自定义的一个配置,用来做自动刷新效果测试。
temp:
notify: 'test value' #在zuul配置增加一个用来测试的配置
#注册到EurekaServer
eureka:
client:
serviceUrl:
defaultZone: http://peer1:1010/eureka/,http://peer2:1011/eureka/,http://peer3:1012/eureka/
#...省略其他配置...
编写controller 我们在controller中读取配置文件中的数据“temp.notify”,当云端的配置文件被修改,我们希望看到controller中的配置“temp.notify”自动刷新
@RestController
@RefreshScope
public class TempController {
@Value("${temp.notify}")
private String notify;
@RequestMapping("/notify")
public String notify(){
return notify;
}
这里的controller方法从配置读取 temp.notify配置项,并返回给浏览器 , @RefreshScope是为了自动触发controller中的配置“ @Value("${temp.notify}")”自动刷新,当然该注解可以贴在配置类上。
2.4.手动刷新配置测试-
启动注册中心,配置中心,zuul ,浏览器访问zuul:http://localhost:1060/notify ,返回 “test value”
-
然后修改Git仓库中zuul的配置文件temp.notify=“test value change” 。
-
然后使用postmain 请求配置中心: http://localhost:1070/monitor
-
访问客户端服务zuul: http://localhost:1060/notify 返回的值应该变成了“test value change”
这里我们通过postmain手动访问 http://localhost:1070/monitor ,触发配置的自动刷新。
2.5.配置自动刷新配置自动刷新即当git仓库(码云)中的配置发生改变自动发送post请求(/monitor)出发配置文件刷新,需要注意的是我们的配置中心是基于本地访问如“http://localhost:1070/monitor”而码云是没办法向一个本地地址发起post请求,我们需要把我们的本地地址映射到公网,所以我们需要做内网穿透。
内网穿透:我这里使用 https://natapp.cn ,官网有使用教程。
这里访问http://q8bzmj.natappfree.cc 如同访问 http://127.0.0.1:1070,同时http://q8bzmj.natappfree.cc 是可以通过外网访问的, 我们需要把 “http://q8bzmj.natappfree.cc/monitor”公网地址配置到码云仓库的WebHook,如下:
当git仓库发生push操作时,自动向 http://q8bzmj.natappfree.cc/monitor 发送post请求实现配置刷新