通过总线机制实现自动刷新客户端配置

方案示意图

利用Git服务的webhook通知功能,在每次更新配置之后,Git服务器会用POST方式调用配置中心的/actuator/bus-refresh接口,配置中心的总线服务会将此事件广播给加入总线的所有客户端,客户端收到事件后会从新读取配置中心的内容。

增加POM依赖

配置中心的服务端(spring-cloud-config-server)和客户端(spring-cloud-config-client)都加入Spring Cloud Bus引用包:

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>

启动Rabbitmq

docker pull rabbitmq:3-management

docker run -d --hostname my-rabbit --name rabbit -p 5672:5672 -p 15672:15672 rabbitmq:3-management

可以访问127.0.0.1:15672/登录rabbitmq管理监控后台,用户名密码都是guest/guest。

修改配置信息

配置中心的服务端(spring-cloud-config-server)和客户端(spring-cloud-config-client)都需要修改配置文件的内容:

spring-cloud-config-server项目的application.properties增加:

# 开启消息跟踪
spring.cloud.bus.trace.enabled=true
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest #显示的暴露接入点
management.endpoints.web.exposure.include=*

spring-cloud-config-client项目的application.properties增加:

# 开启消息跟踪
spring.cloud.bus.trace.enabled=true
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest #显示的暴露接入点
management.endpoints.web.exposure.include=*

spring-cloud-config-client项目的bootstrap.properties增加(否则会报错:A component required a bean named 'configServerRetryInterceptor' that could):

spring.cloud.config.fail-fast=true

配置Git的Webhook





192.168.0.21:9004/actuator/bus-refresh是我一个配置中心的地址,如果有多个配置中心可以写多个webhook,在页面上测试中如果返回204就说明成功了。

将Webhook的POST请求中的body清空

Git在进行webhood post请求的同时默认会在body加上这么一串载荷(payload),Spring Boot 无法并行化,所以在配置中心服务端(spring-cloud-config-server)新建下面两个类:

此代码参考了:spring_cloud config 配置中心及利用Github实现自动化热加载配置

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.ByteArrayInputStream;
import java.io.IOException; //清空请求中的Body
public class EmptyRequestWrapper extends HttpServletRequestWrapper{ public EmptyRequestWrapper(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();
}
};
}
}
import org.springframework.core.annotation.Order;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException; @WebFilter(filterName = "bodyFilter", urlPatterns = "/*")
@Order(1)
//Git在进行webhood post请求的同时默认会在body加上这么一串载荷(payload),Spring Boot 无法并行化。
public class BusRefreshFilter implements Filter { @Override
public void init(FilterConfig filterConfig) throws ServletException { } @Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest)servletRequest; String url = new String(httpServletRequest.getRequestURI()); //只过滤/actuator/bus-refresh请求
if (!url.endsWith("/bus-refresh")) {
filterChain.doFilter(servletRequest, servletResponse);
return;
} //使用HttpServletRequest包装原始请求达到修改post请求中body内容的目的
EmptyRequestWrapper requestWrapper = new EmptyRequestWrapper(httpServletRequest); filterChain.doFilter(requestWrapper, servletResponse);
} @Override
public void destroy() { }
}

最后在启动类上添加@ServletComponentScan注解

@SpringBootApplication
//启动配置中心
@EnableConfigServer
//启动服务发现
@EnableDiscoveryClient
@ServletComponentScan
public class SpringCloudConfigServerApplication { public static void main(String[] args) {
SpringApplication.run(SpringCloudConfigServerApplication.class, args);
} }

测试自动刷新自动

访问客户端程序127.0.0.1:9006/ConfigTest,得到当前结果Test-8,访问配置中心也是Test-8:





我们更新Git参考将配置内容改为Test-9:





查看配置中心127.0.0.1:9004/ConfigDepot/Test,内容已经改为Test-9,再刷新客户端程序127.0.0.1:9006/ConfigTest,这时配置内容已经成功改成了Test-9,总线事件通知客户端刷新配置成功。





从配置中心服务端和客户端的日志也可看出刷新配置信息的过程:



源码

Github仓库:https://github.com/sunweisheng/spring-cloud-example

通过总线机制实现自动刷新客户端配置(Consul,Spring Cloud Config,Spring Cloud Bus)的更多相关文章

  1. 手动刷新客户端配置内容(Spring Cloud Config)

    手动刷新客户端配置内容 客户端项目增加依赖项 <dependency> <groupId>org.springframework.boot</groupId> &l ...

  2. 实现SpringCloud Config 客户端自动刷新

    文章来源:https://blog.csdn.net/qq_27385301/article/details/82716218 一.简介 在使用SpringCloud Config客户端时,如果Con ...

  3. config配置中心之自动刷新

    自动刷新(自动刷新是基于springcloudbus来实现的,springcloud bus是基于rabbitMQ或者Kafka来实现的) Spring Cloud Bus 将分布式的节点用轻量的消息 ...

  4. webpack学习(三)之web-dev-server不能自动刷新问题

    使用webpack-dev-server中遇到不能浏览器无法自动刷新的问题:寻找多方答案后明白了一些: 下面有一些需要注意的点: 1.webpack-dev-server并不能读取你的webpack. ...

  5. springboot+cloud 学习(五)统一配置中心 spring cloud config + cloud bus + WebHooks +RibbitMQ

    前言 微服务要实现集中管理微服务配置.不同环境不同配置.运行期间也可动态调整.配置修改后可以自动更新的需求,Spring Cloud Config同时满足了以上要求.Spring Cloud Conf ...

  6. Spring Boot + Spring Cloud 构建微服务系统(九):配置中心(Spring Cloud Config)

    技术背景 如今微服务架构盛行,在分布式系统中,项目日益庞大,子项目日益增多,每个项目都散落着各种配置文件,且随着服务的增加而不断增多.此时,往往某一个基础服务信息变更,都会导致一系列服务的更新和重启, ...

  7. Spring Cloud Config(一):聊聊分布式配置中心 Spring Cloud Config

    目录 Spring Cloud Config(一):聊聊分布式配置中心 Spring Cloud Config Spring Cloud Config(二):基于Git搭建配置中心 Spring Cl ...

  8. Spring Cloud Config 分布式配置中心【Finchley 版】

    一. 介绍 1,为什么需要配置中心? 当服务部署的越来越多,规模越来越大,对应的机器数量也越来越庞大,靠人工来管理和维护服务的配置信息,变得困难,容易出错. 因此,需要一个能够动态注册和获取服务信息的 ...

  9. Spring Cloud09: Config 配置中心

    一.概述 什么是配置中心呢,在基于微服务的分布式系统中,每个业务模块都可以拆分成独立自主的服务,由多个请求来协助完成某个需求,那么在某一具体的业务场景中,某一个请求需要调用多个服务来完成,那么就存在一 ...

随机推荐

  1. python笔记(3)---列表

    lst = ["bob","jack","马云","马化腾","王健林"] del lst[1:3] ...

  2. 最简单的注册美区Apple ID方法

    最简单方法注册苹果美区Apple ID 1.打开苹果官网链接 苹果官网 2. 点击右下角的 United States 3. 点击图片中的选项 4.点击右上角的选项创建新的Apple ID 注意是新的 ...

  3. 51nod1730 涂边

    题目描述 题解 八级sb题 显然可以想到状压 枚举当前的宽度\(I\),设\(f[s]\)表示在当前的宽度下选的竖边的状态为s 再设\(g[s1][s2]\)表示状态s1转移到s2的方案数,枚举中间横 ...

  4. qt学习(一)qt三个文件函数的框架

    学到点什么, 而不是复制着什么, 每天敲着别人给的代码,苦涩得改完bug, 就这样一天天的过去, 实质上并没有学到什么, 别人的思想只是拿来借鉴, 你的思想是好是坏都是你的, 不用急着抛弃自己. 从q ...

  5. 百度小程序 配置 app.json 文件

    可以通过配置 app.json 文件,设置 SWAN 的界面.路径.多 TAB 等. app.json 配置项列表如下 属性 类型 必填 描述 pages Array.<string> 是 ...

  6. Ajax中浏览器的缓存问题解决方法

    我们在做项目中,一般提交请求都会通过ajax来提交,但是测试的时候发现,每次提交后得到的数据都是一样的,调试可以排除后台代码的问题,所以问题肯定是出在前台 每次清除缓存后,就会得到一个新的数据,所以归 ...

  7. input el-input 只能输入正整数验证

    字母e在js中属于数字,所以一般的正则匹配 \d 是拦不住字母e 的 正确写法为: onKeypress="return (/[\d]/.test(String.fromCharCode(e ...

  8. TestingWhiz社区版2013版下载地址

    TestingWhiz社区版 https://sourceforge.net/projects/testingwhiz-community-edition/ https://sourceforge.n ...

  9. Redis的消息订阅/发布 Utils工具类

    package cn.cicoding.utils; import org.json.JSONException; import org.json.JSONObject; import redis.c ...

  10. navigation ObtacleCostFunction源码分析

    ObtacleCostFunction 定义了一个ObstacleCostFunction类,继承自Trajectory类,Trajectory类有8个类参 总共有8个类参 double xv_,yv ...