什么是消息总线

消息代理中间件构建一个共用的消息主题让所有微服务实例订阅,当该消息主题产生消息时会被所有微服务实例监听和消费。

消息代理又是什么?消息代理是一个消息验证、传输、路由的架构模式,主要用来实现接收和分发消息,并根据设定好的消息处理流来转发给正确的应用。它在微服务之间起到通信调度作用,减少了服务之间的依赖。

什么是 Spring Cloud Bus

Spring Cloud Bus 是 Spring Cloud 体系内的消息总线,用来连接分布式系统的所有节点。

Spring Cloud Bus 将分布式的节点用轻量的消息代理(RibbitMQ、Kafka)连接起来。可以通过消息代理广播配置文件的更改,或服务之间的通讯,也可以用于监控。解决了微服务数据变更,及时同步的问题。

官方文档:https://cloud.spring.io/spring-cloud-static/spring-cloud-bus/2.2.1.RELEASE/reference/html/

什么时候使用 Spring Cloud Bus

微服务一般都采用集群方式部署,而且在高并发下经常需要对服务进行扩容、缩容、上线、下线的操作。比如我们需要更新配置,又或者需要同时失效所有服务器上的某个缓存,需要向所有相关的服务器发送命令,此时就可以选择使用 Spring Cloud Bus 了。

总的来说,就是在我们需要把一个操作散发到所有后端相关服务器的时候,就可以选择使用 Spring Cloud Bus 了。

接下来我们通过 Spring Cloud Bus 实现微服务架构的配置刷新。

环境准备

RibbitMQ v3.8.2 地址:192.168.10.101

bus-demo 聚合工程。SpringBoot 2.2.4.RELEASESpring Cloud Hoxton.SR1

  • eureka-server:注册中心
  • eureka-server02:注册中心
  • config-server:配置中心服务端
  • config-server02:配置中心服务端
  • order-service:订单服务(配置中心客户端)
  • order-service02:订单服务(配置中心客户端)

配置文件 order-service-prod.yml

  1. spring:
  2. application:
  3. name: order-service # 应用名称
  4. # 配置 Eureka Server 注册中心
  5. eureka:
  6. instance:
  7. prefer-ip-address: true # 是否使用 ip 地址注册
  8. instance-id: ${spring.cloud.client.ip-address}:${server.port} # ip:port
  9. client:
  10. service-url: # 设置服务注册中心地址
  11. defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/
  12. # 自定义配置
  13. name: order-service-prod
  14. password: root

Spring Cloud Bus 实现配置刷新

客户端发起通知

点击链接观看:客户端发起通知视频(获取更多请关注公众号「哈喽沃德先生」)

消息总线(Bus)的典型应用场景就是配置中心客户端刷新。

我们在学习 Spring Cloud Config 配置中心时给大家讲了基于 Actuator 的配置刷新,当时的案例只有一个 Config Client,我们可以使用 Webhook,设置手动刷新都不算太费事,但是如果客户端比较多的情况下,一个一个去手动刷新未免有点复杂,这种方案就不太适合了。使用 Spring Cloud Bus 可以完美解决这一问题。

借助 Spring Cloud Bus 的广播功能,让 Config Client 都订阅配置更新事件,当配置更新时,触发其中一个端的更新事件,Spring Cloud Bus 就把此事件广播到其他订阅客户端,以此来达到批量更新。

  1. Webhook 监听被触发,给 ConfigClient A 发送 bus-refresh 请求刷新配置
  2. ConfigClient A 读取 ConfigServer 中的配置,并且发送消息给 Bus
  3. Bus 接收消息后广播通知其他 ConfigClient
  4. 其他 ConfigClient 收到消息重新读取最新配置

添加依赖

Config Client 添加 spring cloud starter bus amqp 依赖。

  1. <!-- spring cloud starter bus amqp 依赖 -->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-bus-amqp</artifactId>
  5. </dependency>

配置文件

配置文件需要配置 消息队列bus-refresh 自动刷新端点。/actuator/bus-refresh 端点会清除 @RefreshScope 缓存重新绑定属性。

Config Client 的 bootstrap.yml 核心配置。

  1. spring:
  2. cloud:
  3. config:
  4. name: order-service # 配置文件名称,对应 git 仓库中配置文件前半部分
  5. label: master # git 分支
  6. profile: prod # 指定环境
  7. discovery:
  8. enabled: true # 开启
  9. service-id: config-server # 指定配置中心服务端的 service-id
  10. # 消息队列
  11. rabbitmq:
  12. host: 192.168.10.101
  13. port: 5672
  14. username: guest
  15. password: guest
  16. virtual-host: /
  17. # 度量指标监控与健康检查
  18. management:
  19. endpoints:
  20. web:
  21. base-path: /actuator # 访问端点根路径,默认为 /actuator
  22. exposure:
  23. include: bus-refresh # 需要开启的端点
  24. #exclude: # 不需要开启的端点

测试

查看端点

访问:http://localhost:9091/actuator 可以看到已经开启了 bus-refresh 自动刷新端点。

访问:http://localhost:9091/name 和 http://localhost:9092/name 结果如下:

修改 Git 仓库配置

修改 Git 仓库配置信息如下:

  1. # 自定义配置
  2. name: order-service-prod-1.0
自动刷新

刷新页面发现结果并未改变,没事正常。

通过 Post 方式调用「任意客户端」的自动刷新端点:http://localhost:9091/actuator/bus-refresh 再次访问结果如下:

查看队列

再来观察一下消息队列的 UI 界面,发现多了一个 springCloudBus 的交换机。

该交换机下绑定了两个队列对应我们的两个 Config Client。

客户端发起通知缺陷

  • 打破了微服务的职责单一性。微服务本身是业务模块,它本不应该承担配置刷新的职责。
  • 破坏了微服务各节点的对等性。
  • 存在一定的局限性。例如,微服务在迁移时,它的网络地址常常会发生变化,此时如果想要做到自动刷新,就不得不修改Webhook 的配置。

服务端发起通知

点击链接观看:服务端发起通知视频(获取更多请关注公众号「哈喽沃德先生」)

为了解决客户端发起通知缺陷,我们改用服务端发起通知。

  1. Webhook监听被触发,给 ConfigServer 发送 bus-refresh 请求刷新配置
  2. ConfigServer 发送消息给 Bus
  3. Bus 接收消息后广播通知所有 ConfigClient
  4. 各 ConfigClient 收到消息重新读取最新配置

添加依赖

Config Server 添加 spring cloud starter bus amqp 依赖。

  1. <!-- spring cloud starter bus amqp 依赖 -->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-bus-amqp</artifactId>
  5. </dependency>

配置文件

配置文件需要配置 消息队列bus-refresh 自动刷新端点。/actuator/bus-refresh 端点会清除 @RefreshScope 缓存重新绑定属性。

Config Server 的 application.yml 核心配置。

  1. spring:
  2. application:
  3. name: config-server # 应用名称
  4. cloud:
  5. config:
  6. server:
  7. git:
  8. uri: https://github.com/imrhelloworld/config-repo # 配置文件所在仓库地址
  9. #username: # Github 等产品的登录账号
  10. #password: # Github 等产品的登录密码
  11. #default-label: master # 配置文件分支
  12. #search-paths: # 配置文件所在根目录
  13. # 消息队列
  14. rabbitmq:
  15. host: 192.168.10.101
  16. port: 5672
  17. username: guest
  18. password: guest
  19. virtual-host: /
  20. # 配置 Eureka Server 注册中心
  21. eureka:
  22. instance:
  23. prefer-ip-address: true # 是否使用 ip 地址注册
  24. instance-id: ${spring.cloud.client.ip-address}:${server.port} # ip:port
  25. client:
  26. service-url: # 设置服务注册中心地址
  27. defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/
  28. # 度量指标监控与健康检查
  29. management:
  30. endpoints:
  31. web:
  32. base-path: /actuator # 访问端点根路径,默认为 /actuator
  33. exposure:
  34. include: bus-refresh # 需要开启的端点
  35. #exclude: # 不需要开启的端点

测试

查看端点

访问:http://localhost:8888/actuator 可以看到已经开启了 bus-refresh 自动刷新端点。

访问:http://localhost:9091/name 和 http://localhost:9092/name 结果如下:

修改 Git 仓库配置

修改 Git 仓库配置信息如下:

  1. # 自定义配置
  2. name: order-service-prod-2.0
自动刷新

刷新页面发现结果并未改变,没事正常。

通过 Post 方式调用「任意服务端」的自动刷新端点:http://localhost:8888/actuator/bus-refresh 再次访问结果如下:

查看队列

再来观察一下消息队列的 UI 界面,发现多了一个 springCloudBus 的交换机。

该交换机下绑定了四个队列对应我们的两个 Config Server 和两个 Config Client。

局部刷新

假设有这样一种场景,我们开发了一个新的功能,此时需要对该功能进行测试。我们只希望其中一个微服务的配置被更新,等功能测试完毕,正式部署线上时再更新至整个集群。但是由于所有微服务都受 Spring Cloud Bus 的控制,我们更新了其中一个微服务的配置,就会导致其他服务也被通知去更新配置。这时候局部刷新的作用就体现出来了。

刷新指定服务

修改 Git 仓库配置信息如下:

  1. # 自定义配置
  2. name: order-service-prod-3.0

通过 Post 方式调用「任意服务端」的自动刷新端点:http://localhost:8888/actuator/bus-refresh/order-service:9091 再次访问结果如下:

9091 端口的客户端已经更新配置。

9092 端口的客户端没有更新配置。

刷新指定集群

假设现在功能测试完毕,需要正式部署线上更新至整个集群。但是由于 Spring Cloud Bus 控制着多个微服务集群(订单微服务、商品微服务等),而我们只想更新指定集群下的配置,这个时候就可以使用 Bus 提供的通配符更新方案。

修改 Git 仓库配置信息如下:

  1. # 自定义配置
  2. name: order-service-prod-4.0

通过 Post 方式调用「任意服务端」的自动刷新端点:http://localhost:8888/actuator/bus-refresh/order-service:** 再次访问结果如下:

至此 Bus 消息总线所有的知识点就讲解结束了。

本文采用 知识共享「署名-非商业性使用-禁止演绎 4.0 国际」许可协议

大家可以通过 分类 查看更多关于 Spring Cloud 的文章。

Spring Cloud 系列之 Bus 消息总线的更多相关文章

  1. Spring Cloud 系列之 Stream 消息驱动(二)

    本篇文章为系列文章,未读第一集的同学请猛戳这里:Spring Cloud 系列之 Stream 消息驱动(一) 本篇文章讲解 Stream 如何实现消息分组和消息分区. 消息分组 如果有多个消息消费者 ...

  2. 一起来学Spring Cloud | 第八章:消息总线(Spring Cloud Bus)

    上一章节,我们讲解了分布式配置中心spring cloud config,我们把配置项存放在git或者本地,当我们修改配置时,需要重新启动服务才能生效.但是在生产上,一个服务部署了多台机器,重新启动比 ...

  3. 多项目如何高效协同合作 | springcloud系列之bus消息总线

    前言 在springcloud config章节中我们完成了配种中心的搭建,以及通过配置中心完成配置的抽离通过springcloud config模块我们将配置抽离到git仓库中我们不必要每次为了改配 ...

  4. Spring Cloud 系列之 Stream 消息驱动(一)

    在实际开发过程中,服务与服务之间通信经常会使用到消息中间件,消息中间件解决了应用解耦.异步处理.流量削锋等问题,实现高性能,高可用,可伸缩和最终一致性架构. 不同中间件内部实现方式是不一样的,这些中间 ...

  5. Spring Cloud 系列之 Consul 配置中心

    前面我们已经学习过 Spring Cloud Config 了: Spring Cloud 系列之 Config 配置中心(一) Spring Cloud 系列之 Config 配置中心(二) Spr ...

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

    继上一篇 干货|Spring Cloud Stream 体系及原理介绍 之后,本期我们来了解下 Spring Cloud 体系中的另外一个组件 Spring Cloud Bus (建议先熟悉 Spri ...

  7. 跟我学SpringCloud | 第八篇:Spring Cloud Bus 消息总线

    SpringCloud系列教程 | 第八篇:Spring Cloud Bus 消息总线 Springboot: 2.1.6.RELEASE SpringCloud: Greenwich.SR1 如无特 ...

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

    详见:https://www.w3cschool.cn/spring_cloud/spring_cloud-jl8a2ixp.html 上一篇文章,留了一个悬念,Config Client 实现配置的 ...

  9. spring cloud bus 消息总线 动态刷新配置文件 【actuator 与 RabbitMQ配合完成】

    1.前言 单机刷新配置文件,使用actuator就足够了 ,但是 分布式微服务 不可能是单机 ,将会有很多很多的工程 ,无法手动一个一个的发送刷新请求, 因此引入了消息中间件 ,常用的 消息中间件 是 ...

随机推荐

  1. Laravel - 基础

    1.使用 composer 创建项目 composer create-project --prefer-dist laravel/laravel blog 报错1 [ErrorException]pr ...

  2. [一道蓝鲸安全打卡Web分析] 文件上传引发的二次注入

    蓝鲸打卡的一个 web 文件上传引发二次注入的题解和思考 蓝鲸文件管理系统 源代码地址:http://www.whaledu.com/course/290/task/2848/show 首先在设置文件 ...

  3. 彻底解决Python编码问题

    1. 基本概念 字符集(Character set) 解释:文字和符合的总称 常见字符集: Unicode字符集 ASCII字符集(Unicode子集) GB2312字符集 编码方法(Encoding ...

  4. JDBC 中的事务和批处理 batch

    JDBC事务处理: 事务处理一般在事务开始前把事务提交设置为false 所有DML语句执行完成后提交事务 demo: package com.xzlf.jdbc; import java.sql.Co ...

  5. php-fpm运行原理

    来源:https://blog.csdn.net/sinat_38804294/article/details/94393621 一.php-fpm由来1.cgi (common gateway in ...

  6. .net多线程归并排序

    一.概述 在了解排序算法的同时,想到用多线程排序减少排序的时间,所以写了一个简单的示例,加深印象.下面是具体代码 二.内容 环境:vs2017,.net  core 2.2 控制台程序. 运行时使用r ...

  7. Vue 结合 echarts 原生 html5 实现拖拽排版报表系统

    前言 不知道各位 coder 有没有碰到过许多重复的业务需求,比如排版相类似的报表,只不过是顺序稍微换了一下,就是一个新的页面,虽然基于模板思想来写的话也能减少不少代码,但是相对的不那么方便,笔者最近 ...

  8. 吞吐量(TPS)、QPS、并发数、响应时间(RT)

    1. 响应时间(RT)  响应时间是指系统对请求作出响应的时间.直观上看,这个指标与人对软件性能的主观感受是非常一致的,因为它完整地记录了整个计算机系统处理请求的时间.由于一个系统通常会提供许多功能, ...

  9. AWS访问慢的原因分析及解决方案

    中国区的用户在访问海外AWS服务器的时候会遇到访问很慢的情况,那如何快速访问海外AWS服务器,今天和大家一起聊一下这个话题. 首先,为什么中国的用户访问海外AWS会变慢? 我总结来下大概有以下几方面的 ...

  10. 图论--2-SAT--POJ Ikki's Story IV - Panda's Trick

    Description liympanda, one of Ikki's friend, likes playing games with Ikki. Today after minesweeping ...