带你入门SpringCloud 之 通过SpringCloud Bus 自动更新配置
前言
在《带你入门springcloud统一配置 | springcloud config》中通过 springcloud config 完成了统一配置基础环境搭建,但是并没有实现配置修改自动更新的操作(github 或gitee 修改配置后,需要重启配置服务才能更新配置)。
本文是《带你入门springcloud统一配置 | springcloud config》的续篇,通过 springcloud bus 完成配置修改自动更新的操作介绍。
阅读本文前需要你先移步《带你入门springcloud统一配置 | springcloud config》因为本文是在其基础上进行讲解的。
另外需要你熟悉 springboot 项目的基本使用即可,还有一点需要注意的是在操作过程中尽量和我本地环境一致,因为环境不一致可能会带来一些问题。我本地环境如下:
- springboot version: 2.1.0.release
- springcloud version: greenwich.release
- apache maven version: 3.6.0
- java version: 1.8.0_144
- idea:spring tools suite (sts)
接下来就开始 springcloud bus 环境搭建操作介绍!
springcloud bus 环境搭建
第一步:安装并启用 rabbitmq,这里就不做详细介绍了。可以查看之前的总结:windows 环境安装 rabbitmq
如果你的 rabbitmq和 config server 端不在一台机器上,或者端口、用户名、密码不是使用的默认配置,那么你需要进行如下配置在 config server 端 application.properties 中
spring.rabbitmq.host=rabbitmq 服务ip地址
spring.rabbitmq.port=rabbitmq 服务端口号
spring.rabbitmq.username=rabbitmq 服务用户名
spring.rabbitmq.password=rabbitmq 服务密码
第二步:在 config server 端端和客户端都引入 spring-cloud-starter-bus-amqp 依赖。具体代码如下:
<dependency> <groupid>org.springframework.cloud</groupid> <artifactid>spring-cloud-starter-bus-amqp</artifactid> </dependency>
第三步:在config server 端的 application.properties 中需要添加如下配置,目的是把刷新配置接口暴露出来,具体配置如下:
management.endpoints.web.exposure.include= *
第四步:config client 端引入openfeign starter 依赖,具体代码如下:
<dependency> <groupid>org.springframework.cloud</groupid> <artifactid>spring-cloud-starter-openfeign</artifactid> </dependency>
第五步:验证 config server 端和 config client 端是否在 rabbitmq 注册队列和是否注册到 eureka server 端上。如下图所示:
需要先启动 eureka server 服务端,然后在依次启动 config server端和config client端。
第六步:config client 端*问配置的 controller 声明刷新配置作用域@refreshscope。具体代码如下:
@restcontroller @refreshscope public class evncontroller { @value("${env}") private string env; @requestmapping("/env") public string evn() { return this.env; } }
不添加 @refreshscope注解,配置更新后不会生效。
如果是自定义前缀配置需要在@configurationproperties下添加 @refreshscope即可,
最七步在 gitee 上配置 webhooks,具体操作方式如下图所示:
进入gitee 点击管理,然后点击 webhooks。
点击添加按钮添加新的 webhooks 设置。
输入本地映射外网访问域名+/actuator/bus-refresh,自己测试可以使用 natapp 进行内网穿穿透配置。具体配置请查看 https://natapp.cn/。
测试
手动访问更新链接进行测试
修改配置在码云远程仓库上,然后使用 postman 访问:http://localhost:8080/actuator/bus-refresh ,如下图所示:
这里演示直接是在码云上操作,相当于执行 git push 操作。
然后在查看商品服务(config client端)配置是否生效。如下图所示自动更新成功!
webhooks 测试
进入 webhooks 设置,然后点击测试。会报如下图所示错误:
解决方案:
参考来csdn 作者 解决方案。
文章: (https://blog.csdn.net/m0_37556444/article/details/82812816)
问题产生原因:github在进行 post 请求的同时默认会在 body 加上这么一串载荷(payload),而 /actuator/bus-refresh 接口没有进行接受这些信息处理,所以就报错了。
解决问题思路:通过拦截器拦截 bus-refresh请求,然后在 httpservletrequestmapper 包装类将 request中 body 内容置空。具体代码如下:
拦截 bus-refresh请求filter 类。
public class busrefreshfilter implements filter{ @override public void dofilter(servletrequest request, servletresponse response, filterchain chain) throws ioexception, servletexception { httpservletrequest httpservletrequest = (httpservletrequest)request; string url = new string(httpservletrequest.getrequesturi()); //只过滤/actuator/bus-refresh请求 if (!url.endswith("/bus-refresh")) { chain.dofilter(request, response); return; } //使用httpservletrequest包装原始请求达到修改post请求中body内容的目的 custometrequestwrapper requestwrapper = new custometrequestwrapper(httpservletrequest); chain.dofilter(requestwrapper, response); } }
自定义 httpservletrequestwrapper 类
public class custometrequestwrapper extends httpservletrequestwrapper{ public custometrequestwrapper(httpservletrequest request) { super(request); } @override public servletinputstream getinputstream() throws ioexception { byte[] bytes = new byte[0]; bytearrayinputstream bytearrayinputstream = new bytearrayinputstream(bytes); return new servletinputstream() { @override public boolean isfinished() { return bytearrayinputstream.read() == -1 ? true:false; } @override public boolean isready() { return false; } @override public void setreadlistener(readlistener readlistener) { } @override public int read() throws ioexception { return bytearrayinputstream.read(); } }; } }
将拦截 bus-refresh请求filter 添加到 spring 上下文中配置类。
@configuration public class filterconfig { @bean public filterregistrationbean<busrefreshfilter> filterregistration() { filterregistrationbean<busrefreshfilter> registration = new filterregistrationbean<busrefreshfilter>(); registration.setfilter(new busrefreshfilter()); list<string> urllist = new arraylist<string>(); urllist.add("/*"); registration.seturlpatterns(urllist); registration.setname("busrefreshfilter"); registration.setorder(1); return registration; } }
然后修改gitee 上的配置信息后就可以自动更新了,这里就不在进行演示操作来。
还有一种方式是通过访问 config server端域名/monitor 来取代 config server端域名//actuator/bus-refresh。本方式个人尝试没有成功!具体配置官网介绍如下:
many source code repository providers (such as github, gitlab, gitea, gitee, gogs, or bitbucket) notify you of changes in a repository through a webhook. you can configure the webhook through the provider’s user interface as a url and a set of events in which you are interested. for instance, github uses a post to the webhook with a json body containing a list of commits and a header (x-github-event) set to push. if you add a dependency on the spring-cloud-config-monitor library and activate the spring cloud bus in your config server, then a /monitor endpoint is enabled.
在config server 添加 spring-cloud-config-monitor 依赖
<dependency> <groupid>org.springframework.cloud</groupid> <artifactid>spring-cloud-config-monitor</artifactid> </dependency>
然后在config client 添加如下配置:
参考:
spring.cloud.bus.id=${vcap.application.name:${spring.application.name:application}}:${vcap.application.instance_index:${spring.profiles.active:${local.server.port:${server.port:0}}}}:${vcap.application.instance_id:${random.value}}
小结
当将远程仓库配置文件修改后,通过github 或者 gitee 的 webhooks 配置自动访问接口bus-refresh 来通知config server 端。
config server 端收到请求后将配置 clone 下来,然后通过消息队列(默认是rabbitmq)将修改后的配置发送给 config client 端。config client 端收到消息后重新从config server 端获取最新的配置信息。
而webhooks 配置请求接口 bus-refresh 和消息队列发送配置给 config client 端都是 springcloud bus 帮助我们完成的。
代码示例
如果你按照上述方式搭建并未成功,可以参考我在github 项目 仓库中模块名为:
spring-cloud-config-eureka-service
spring-cloud-config-server
spring-cloud-config-product-service
进行对比查看是否配置有误。
spring-cloud-get-started 项目地址:
参考文献
by
上一篇: Java 比较器的用法
下一篇: Java生产消费者模型——代码解析