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

方案示意图

利用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. LeetCode--072--编辑距离(python)

    给定两个单词 word1 和 word2,计算出将 word1 转换成 word2 所使用的最少操作数 . 你可以对一个单词进行如下三种操作: 插入一个字符删除一个字符替换一个字符示例 1: 输入: ...

  2. CSS颜色和长度单位

    颜色 如果我们相给页面设置颜色可以采用多种方法进行设置: 一.命名颜色 假设在设置页面的颜色时觉得一部分很小的颜色集中就足够了,就可以直接给定颜色的名称.CSS称这些有名称的颜色为命名颜色. 命名颜色 ...

  3. 超赞的Linux软件分享(持续更新)

    开发 Android studio - Android 的官方 IDE:Android Studio 提供在各种类型的安卓设备上构建应用最快的工具. Aptana - Aptana Studio 利用 ...

  4. 基于点云的3ds Max快速精细三维建模方法及系统的制作方法 插件开发

                                 基于点云的3ds Max快速精细三维建模方法及系统的制作方法[技术领域][0001]本发明涉及数字城市三维建模领域,尤其涉及一种基于点云的3d ...

  5. Spring Cloud教程(十)自定义引导配置属性源

    可以通过在org.springframework.cloud.bootstrap.BootstrapConfiguration键下添加条目/META-INF/spring.factories来训练引导 ...

  6. StringUtils.join()

    org.apache.commons.lang.StringUtils; StringUtils.join(null)            = null StringUtils.join([])   ...

  7. Django项目执行时No Module Named ' ' 问题的解决情况

    出现这种问题的情况大致都是因为该模块未安装,使用 pip install xxx 进行安装,即可解决此类问题. 出现ModuleNotFoundError: No module named 'rest ...

  8. 【C++】fill函数,fill与memset函数的区别

    转载自:https://blog.csdn.net/liuchuo/article/details/52296646 memset函数 按照字节填充某字符在头文件<cstring>里面fi ...

  9. PHP版本问题

    PHP 5.3以下版本 无法用下标直接取得函数返回的数组 eg: $val_0 = explode(',', $val)[0]//报错 #要改成: $exploded_val = explode(', ...

  10. sqlalchemy批量添加数据-数据源是json(小算法)

    需求: 想要写1个增加case的接口 问题: sqlalchemy添加case的方式,只能是1条数据1条数据的插入,像这样: ro2 = Role(name='user') db.session.ad ...