一、简介

前面我们介绍了如何通过/refresh接口手动刷新配置文件内容,但是,当我们的系统中服务越来越多之后,维护这样的刷新清单将会变得非常繁琐麻烦,而且容易犯错。本章介绍使用Spring Cloud Bus消息总线实现配置文件的集群动态刷新。Bus消息代理中间件可以将消息路由到一个或多个目的地。

二、准备工程

【a】eureka-server: 服务注册中心,端口1111;

【b】config-server: 配置服务中心, 端口2222;

【c】config-client: 服务消费者,端口3333;

这里对eureka服务注册中心的搭建不做详细讲解,比较简单。下面我们新建springcloud_config_server工程,引入spring-cloud-config-server,具体pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.springcloud.wsh</groupId><artifactId>springcloud_config_server</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>springcloud_config_server</name><description>Demo project for Spring Boot</description><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.2.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version><spring-cloud.version>Camden.SR6</spring-cloud.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-config-server</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-eureka</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

三、启动类加上@EnableConfigServer,@EnableDiscoverClient

@SpringBootApplication
@EnableDiscoveryClient
@EnableConfigServer
public class SpringcloudConfigServerApplication {public static void main(String[] args) {SpringApplication.run(SpringcloudConfigServerApplication.class, args);}
}

配置文件application.yml:

server:port: 2222
spring:application:name: config-servercloud:config:server:git:search-paths: repositoryusername: 对应你的git用户名password: 对应你的git密码uri: 对应你git仓库路径label: master
eureka:client:serviceUrl:defaultZone: http://localhost:1111/eureka/

注意:如果配置文件中含有中文,需要自定义PropertySourceLoader解决,解决方法见https://blog.csdn.net/Weixiaohuai/article/details/82759084。

四、新建springcloud_config_client

【a】引入一些必须的依赖: spring-cloud-starter-bus-amqp、spring-boot-starter-actuator、spring-cloud-starter-config等,具体pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.springcloud.wsh</groupId><artifactId>springcloud_config_client</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>springcloud_config_client</name><description>Demo project for Spring Boot</description><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.2.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version><spring-cloud.version>Camden.SR6</spring-cloud.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-config</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-eureka</artifactId></dependency><!--消息总线功能--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bus-amqp</artifactId></dependency><!--开启监控功能--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

【b】配置文件bootstrap.yml:主要配置git仓库路径,分支等

server:port: 3333
#注意application-name(配置文件前缀)需要对应git仓库中 config-client-dev、config-client-test、config-client-prod为名称的配置文件
spring:application:name: config-clientcloud:config:#指定当前所属环境profile: devdiscovery:#开启通过服务访问config-server的功能enabled: true#指定配置中心注册到eureka的serviceId(即config-server的application-name)serviceId: config-server#git仓库分支label: master
eureka:client:serviceUrl:defaultZone: http://localhost:1111/eureka/

配置文件application.yml:主要配置权限拦截、rabbitmq消息中间件支持

#RabbitMQ相关配置
spring:rabbitmq:port: 5672username: guestpassword: guestvirtual-host: /host: localhost
#忽略权限拦截
management:security:enabled: false

【c】启动类

@SpringBootApplication
@EnableDiscoveryClient
public class SpringcloudConfigClientApplication {public static void main(String[] args) {SpringApplication.run(SpringcloudConfigClientApplication.class, args);}
}

【d】暴露接口给外部访问

注意加上@RefreshScope注解

/*** 测试客户端从配置服务中心获取配置文件中的内容** @author weishihuai* @date 2018/9/26 10:59*/
@RestController
//@RefreshScope注解的作用: 如果刷新了bean,那么下一次访问bean(即执行一个方法)时就会创建一个新实例。
@RefreshScope
public class GetPropertyFromConfigServerController {private static Logger logger = LoggerFactory.getLogger(GetPropertyFromConfigServerController.class);@Value("${com.springcloud.wsh.message}")String message;@RequestMapping("/getPropertyFromConfigServer")public String getPropertyFromConfigServer() {String msg = "hello, i am " + message + ", i'm come from config server";logger.info(msg);return msg;}}

五、启动项目

依次启动eureka-server、config-server、config-client(可以启动多个实例,这里启动两个实例,端口分别是3333和4444)。启动config-client客户端时,控制台可以看到客户端程序多了一个/bus/refresh请求。

【a】分别访问请求http://localhost:3333/getPropertyFromConfigServer和http://localhost:4444/getPropertyFromConfigServer,如下图,分别返回当前git仓库中config-client-dev.properties配置文件中的内容:

【b】然后,我们通过git工具修改git仓库中config-client-dev.properties配置文件中的内容:

并发送POST请求/bus/refresh,http://localhost:3333/bus/refresh或者http://localhost:4444/bus/refresh,其中一个都可以

执行完之后,配置会通知到消息总线上,这样会扫描@ScopeRefresh注解注释的Bean,重新创建一个实例,这样所有监听消息总线的服务都可以获取最新的配置文件信息。

【c】最后,我们再分别访问http://localhost:3333/getPropertyFromConfigServer和http://localhost:4444/getPropertyFromConfigServer,此时两个请求返回的配置文件信息都是最新的。

至此,我们已经实现了通过Spring Cloud Bus来实时更新总线上的属性配置。

六、原理总结

这里,我简单的画了一个基本的原理图。总结两点:

【a】Config Client1、Config Client2、Config Client3都从Config Server中获取配置信息,服务配置中心从git远程仓库获取配置信息,这时候我们在各个服务消息者客户端可以成功获取到git中配置文件信息。

【b】假设,我们对Config Client3的配置内容进行了修改,这时候Config Client1、Config Client2、Config Client3中的配置信息其实并没有更新到最新的,还是以前的。只有我们向Config Client3发送/bus/refresh的post请求之后,因为Config Client3会通过RabbitMQ通知到消息总线上,这样监听消息总线上的Config Client1和Config Client2都能从消息总线上获取到最新的配置信息,从而实现配置信息的动态更新。

七、指定刷新范围

有时候在特殊场景下,我们只需要刷新某个服务或者某个实例的配置,Spring Cloud Bus提供了destination参数来实现只更新部分配置。

【a】某个实例更新:/bus/refresh?destination=config-client:3333,只更新端口为3333的config-client服务实例

【b】某个服务的全部实例更新: /bus/refresh?destination=config-client:**,这样会更新config-client服务的所有实例

八、优化

由上面原理总结的图可以看到,我们使用/bus/refresh发送到我们其中一个config-client中,然后再同步更新整个服务的配置文件信息,这样这个实例就跟其他实例不一致,额外承担了刷新配置的功能。试想一下,能否将发送post请求刷新配置的任务交由config-server配置服务中心来处理,这样所有服务实例都是对等,由配置服务中心发送消息通知消息总线更新整个集群中的配置。通过上面的改动,服务实例就不需要再承担触发配置更新的任务。

九、总结

以上就是使用Spring Cloud Bus消息总线实现配置动态刷新的功能,同时还谈到了一种优化的方案,让配置服务中心去发送/bus/refresh 请求去执行更新配置任务。本文是作者在学习消息总线的一些总结,仅供大家参考,共同学习,共同进步。

Spring Cloud Bus消息总线(学习总结)相关推荐

  1. Spring Cloud(十一)高可用的分布式配置中心 Spring Cloud Bus 消息总线集成(RabbitMQ)

    上一篇文章,留了一个悬念,Config Client 实现配置的实时更新,我们可以使用 /refresh 接口触发,如果所有客户端的配置的更改,都需要手动触发客户端 /refresh ,当服务越来越多 ...

  2. Spring Cloud Bus 消息总线介绍

    作者 | 洛夜 来源 | 阿里巴巴云原生公众号 在 Spring 生态中玩转 RocketMQ 系列文章: <如何在 Spring 生态中玩转 RocketMQ?> <罗美琪和春波特 ...

  3. 干货|Spring Cloud Bus 消息总线介绍

    2019独角兽企业重金招聘Python工程师标准>>> 继上一篇 干货|Spring Cloud Stream 体系及原理介绍 之后,本期我们来了解下 Spring Cloud 体系 ...

  4. Spring Cloud Bus 消息总线实现配置自动刷新

    why 当微服务太多的时候,服务之间需要建立通信或一个服务的改变需要广播到所有其它服务,这时就需要有一个总线来承担对应的职责. what spring cloud bus 是通过轻量消息代理连接各个分 ...

  5. Spring Cloud Bus 消息总线

    在微服务架构的系统中,我们通常会使用轻量级的消息代理来构建一个共用的消息主题让系统中所有微服务实例都连接上来,由于该主题中产生的消息会被所有实例监听和消费, 所以称它为消息总线. 在总线上的各个实例都 ...

  6. Spring Cloud Bus消息总线

    目录 一.概述简介 1.1. Bus是什么 1.2. Bus能干嘛 1.3. 为何被称为总线 二.RabbitMQ环境配置 2.1. windows下载与安装 2.2. 使用RabbitMQ 三.Bu ...

  7. Spring Cloud Bus + RabbitMq 自动刷新

    2019独角兽企业重金招聘Python工程师标准>>> 最近两天在鼓捣Spring Cloud Bus消息总线的刷新机制问题,探索的路程总是坎坷的,一些坑是逃不掉的,总算将其大概了解 ...

  8. SpringCloud学习(八)消息总线(Spring Cloud Bus)(Finchley版本)

    Spring Cloud Bus 将分布式的节点用轻量的消息代理连接起来.它可以用于广播配置文件的更改或者服务之间的通讯,也可以用于监控.本文要讲述的是用Spring Cloud Bus实现通知微服务 ...

  9. SpringCloud学习笔记 - 消息总线 - Spring Cloud Bus

    1. 消息总线简介 消息代理中间件构建了一个共用的消息主题让所有微服务实例订阅,当该消息主题产生消息时会被所有微服务实例监听和消费. 消息代理又是什么?消息代理是一个消息验证.传输.路由的架构模式,主 ...

  10. Spring Cloud学习:07消息总线(Spring Cloud Bus)

    2019独角兽企业重金招聘Python工程师标准>>> 1 消息总线介绍 消息总线是一种通信工具,可以在机器之间互相传输消息.文件等.消息总线扮演着一种消息路由的角色,拥有一套完备的 ...

最新文章

  1. 2022-2028年中国电子灌封胶行业市场研究及前瞻分析报告
  2. 北大高材生割美国韭菜被FBI通缉?本人回应予以否认
  3. 使用String.format简化代码
  4. Ie html button消失,input 按钮在IE下显现不一致的兼容问题
  5. Linux设备驱动中的并发控制总结
  6. wampServer配置WWW根目录遇到的坑
  7. Android开发用到的几种常用设计模式浅谈(一):组合模式
  8. LeetCode 2011. 执行操作后的变量值
  9. java数组的四个要素_Java零基础系列教程04Java数组
  10. Anagram Groups(字符串)
  11. Python笔记:Python中的main函数
  12. 【Linux开发】linux设备驱动归纳总结(四):3.抢占和上下文切换
  13. WINDOWS CMAKE与NMAKE
  14. Asp.NET之入门
  15. fiddler界面工具栏介绍
  16. java halt_Java Runtime halt()方法
  17. OA(二)编写基本的CURD
  18. 2022年免费企业邮箱大全,用免费邮箱发邮件安全吗?
  19. 计算机的组成以及其功能
  20. 自学python后自己接单-详解 | Python学多久才能独立接单赚钱?一个月足够了!

热门文章

  1. Jupyter Notebook从入门到精通
  2. 从客户端登陆服务器的配置文件,从客户端登陆服务器的配置
  3. jupyter notebook添加虚拟环境
  4. 递归二叉树的序列打印
  5. 可视化修改SQL服务器名字,修改sql server服务器名称
  6. 怎样打开android设备,在app中打开android设备的存储
  7. EDSR:Enhanced Deep Residual Networks for Single Image Super-Resolution
  8. CS231n李飞飞计算机视觉 卷积神经网络详解上
  9. the true story about using data mining to identify a relation between sales of beer and diapers
  10. 【PRML 学习笔记】第二章 - 概率分布 (Probability Distributions)