通过总线机制实现自动刷新客户端配置(Consul,Spring Cloud Config,Spring Cloud Bus)

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

方案示意图

利用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

原文地址:https://www.cnblogs.com/bluersw/p/11610722.html

时间: 2024-10-07 12:50:53

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

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

手动刷新客户端配置内容 客户端项目增加依赖项 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> 客户端项目修改配置文件 增加management.endpoints.web.exposure.include=refresh,health,

config配置中心之自动刷新

自动刷新(自动刷新是基于springcloudbus来实现的,springcloud bus是基于rabbitMQ或者Kafka来实现的) Spring Cloud Bus 将分布式的节点用轻量的消息代理连接起来.它可以用于广播配置文件的更改或者服务之间的通讯,也可以用于监控.本文要讲述的是用Spring Cloud Bus实现通知微服务架构的配置文件的更改,即实现配置中心的自动刷新和批量更新. 这里选择rabbitMQ:为什么呢,它是pivotal的产品: 以下几个都是他们家的,还是很强大的.

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

使用webpack-dev-server中遇到不能浏览器无法自动刷新的问题:寻找多方答案后明白了一些: 下面有一些需要注意的点: 1.webpack-dev-server并不能读取你的webpack.config.js的配置output!! 你在webpack.config.js里面的配置output属性是你用webpack打包时候才起作用的,对webpack-dev-server并不起作用 2.webpack-dev-server打包生产的文件并不会添加在你的项目目录中!! 它默认打包的文件名

spring cloud 使用spring cloud bus自动刷新配置

Spring Cloud Bus提供了批量刷新配置的机制,它使用轻量级的消息代理(例如RabbitMQ.Kafka等)连接分布式系统的节点,这样就可以通过Spring Cloud Bus广播配置的变化或者其他的管理指令.使用Spring Cloud Bus后的架构如图9-2所示. 图9-2 使用Spring Cloud Bus的架构图 由图可知,微服务A的所有实例通过消息总线连接到了一起,每个实例都会订阅配置更新事件.当其中一个微服务节点的/bus/refresh端点被请求时,该实例就会向消息总

Spring Cloud 入门教程(三): 配置自动刷新

之前讲的配置管理, 只有在应用启动时会读取到GIT的内容, 之后只要应用不重启,GIT中文件的修改,应用无法感知, 即使重启Config Server也不行. 比如上一单元(Spring Cloud 入门教程(二): 配置管理)中的Hello World 应用,手动更新GIT中配置文件config-client-dev.properties的内容(别忘了用GIT push到服务器) hello=Hello World from GIT version 1 刷新 http://locahost/8

springcloud21---Config-bus实现配置自动刷新

Pivotal(毕威拓)有VMware和EMC成立的. RabbitMQ是由ERlang(爱立信开发的,面向并发的编程语言),安装RabbitMQ先要安装ERlang. package com.itmuch.cloud; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import

【转】新浪微博手机客户端刷新都是手动刷新或者下拉刷新,为什么不设计成自动刷新?

一是将主动权交给用户:二是为用户的流量着想:三是自动刷新容易造成用户的反感(即用户体验差). 1.关于点入时自动刷新 进入时是否自动刷新新浪微博和腾讯微博分成两派. 新浪微博进入时不自动刷新.碎片化的阅读时间,可为用户保留阅读进度:节省用户流量:将阅读主动权交给用户. 腾讯微博进入时自动刷新.此点相较之下不够人性化.不过对比新浪,痛点在于活跃用户少.互动质量差,UGC也较少.对于众多的非活跃用户,下载了客户端,偶尔点进去一次,自动刷新告诉你,有这么多新内容,我还活着啊,我还很活跃啊. 2.关于按

NFS客户端配置为开机自动挂载报错(二)

NFS客户端配置为开机自动挂载时,系统启动报错. 报错信息类似: mount: mount: mount to NFS server '172.16.1.254' failed: mount: System Error: No route to host. 原因:网络启动后需要对网络内路由表进行"学习".在未完成路由表学习之前启动netfs服务会报错. 解决方法:延后netfs启动时间.(延时时间以实际情况为准,建议30秒) 示例: 修改:/etc/init.d/netfs脚本 在如下

Spring+Rmi中的客户端自动重连配置

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN"   "http://www.springframework.org/dtd/spring-beans.dtd"><beans>    <bean id="xxx" class="org.s