SpringCloud实战---第十七篇:消息总线SpringCloudBus

举报
老司机张师傅 发表于 2022/07/26 23:25:20 2022/07/26
【摘要】 系列文章目录SpringCloud快速入门到精通各组件原理专栏传送门@TOC 前言 我们学习的知识框架图继上篇SpringCloud实战—第十六篇:微服务配置中心# 一、Bus消息总线是什么- 上篇我们说到,Config解决了统一配置中心的问题,但是每次修改配置都要重启程序或手动访问接口,这样显然不够灵活也不太方便。- 分布式自动刷新配置功能,通常和Config分布式配置中心一起使用,他的...

系列文章目录

SpringCloud快速入门到精通各组件原理
专栏传送门


@TOC


前言

我们学习的知识框架图

在这里插入图片描述
继上篇SpringCloud实战—第十六篇:微服务配置中心


# 一、Bus消息总线是什么 - 上篇我们说到,Config解决了统一配置中心的问题,但是每次修改配置都要重启程序或手动访问接口,这样显然不够灵活也不太方便。 - 分布式自动刷新配置功能,通常和Config分布式配置中心一起使用,他的原理是通过RabitMQ或Kafka消息队列,git上的配置修改时发布消息通知,然后配置中心调用我们上篇手动访问的接口来实现自动刷线配置。 - Spring Cloud Bus 配合 Spring Cloud Config 使用可以实现配置的动态刷新。Spring Cloud Bus是用来将分布式系统的节点与轻量级消息系统链接起来的框架,它整合了Java的事件处理机制和消息中间件的功能。Spring Clud Bus目前支持RabbitMQ和Kafka。 - Bus支持两种消息代理:RabbitMQ 和 Kafka - Spring Cloud Bus能管理和传播分布式系统间的消息,就像一个分布式执行器,可用于广播状态更改、事件推送等,也可以当作微服务间的通信通道。 - 总线在微服务架构的系统中,通常会使用轻量级的消息代理来构建一个共用的消息主题,并让系统中所有微服务实例都连接上来。由于该主题中产生的消息会被所有实例监听和消费,所以称它为消息总线。在总线上的各个实例,都可以方便地广播一些需要让其他连接在该主题上的实例都知道的消息。 基本原理ConfigClient实例都监听MQ中同一个topic(默认是springCloudBus)。当一个服务刷新数据的时候,它会把这个信息放入到Topic中,这样其它监听同一Topic的服务就能得到通知,然后去更新自身的配置。

二、搭建环境

可以从我上传的百度网盘的资源下载相关安装包(windows下)

链接:https://pan.baidu.com/s/1mrql-G6cg0LHKrtgBoGQRw 
提取码:pkhg

授人以鱼不如授人以渔,以下是安装包下载的方式:

1. 安装Erlang

Erlang是RabitMQ的依赖环境,注意:Erlang和RabitMQ的版本是有版本对应关系的,可以访问以下网址进行查看:

https://www.rabbitmq.com/which-erlang.html#compatibility-matrix

进入erlang下载网址

http://erlang.org/download/

拉到最下面,选择合适的版本进行下载
以.exe结尾的是windows下的安装包
在这里插入图片描述
傻瓜式安装,不多解释
安装好后设置下环境变量,不会的自行百度。

2. 安装RabitMQ

先下载安装包

https://www.rabbitmq.com/download.html

在这里插入图片描述
也是傻瓜式安装,下一步,选下安装目录,然后一直下一步即可。
cmd小窗口进入到RabitMQ的安装目录下的sbin目录,输入以下命令开启可视化插件

rabbitmq-plugins enable rabbitmq_management

在这里插入图片描述
启动

rabbitmq-server start

在这里插入图片描述
访问地址,查看可视化界面

http://localhost:15672/

输入账号密码,账号密码都是guest
在这里插入图片描述
至此说明环境安装成功!

二、Bus动态刷新模块搭建

1. 创建3366模块

在这里插入图片描述
模块名

cloud-config-client-3366

pom依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-config</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

bootstrap.yml

server:
  port: 3366

spring:
  application:
    name: config-client
  cloud:
    #Config客户端配置
    config:
      label: master #分支名称
      name: config #配置文件名称
      profile: dev #读取后缀名称   上述3个综合:master分支上config-dev.yml的配置文件被读取http://config-3344.com:3344/master/config-dev.yml
      uri: http://localhost:3344 #配置中心地址k

#服务注册到eureka地址
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka

# 暴露监控端点
management:
  endpoints:
    web:
      exposure:
        include: "*"

启动类

package com.atguigu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

/**
 * @auther zzyy
 * @create 2020-02-21 20:04
 */
@EnableEurekaClient
@SpringBootApplication
public class ConfigClientMain3366
{
    public static void main(String[] args)
    {
        SpringApplication.run(ConfigClientMain3366.class,args);
    }
}

编写controller

package com.atguigu.springcloud.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @auther zzyy
 * @create 2020-02-21 18:08
 */
@RestController
@RefreshScope
public class ConfigClientController
{
    @Value("${config.test}")
    private String configTest;

    @GetMapping("/configInfo")
    public String getConfigInfo()
    {
        return configTest;
    }
}

启动rabitmq,7001、3344和3366
访问接口测试3366模块

http://localhost:3366/configInfo

测试成功
在这里插入图片描述

三、基于Bus自动刷新的两种方式

1. 利用消息总线触发一个客户端/bus/refresh,而刷新所有客户端的配置

这种方式bus消息会打在客户端,客户端向bus发送消息通知其他的客户端一起更新远程配置,这种方式给客户端增加了额外的负担,而且一旦这个客户端出现问题其他的客户端也都跟着无法进行消息自动更新了,不太合适。
在这里插入图片描述

2. 利用消息总线触发一个服务端ConfigServer的/bus/refresh端点,而刷新所有客户端的配置

这种方式bus消息打到配置中心,再由配置中心去向Bus发送消息通知客户端更新信息,这种方式显然更加合理。
在这里插入图片描述

3. 方案2优于方案1的原因

  • 方案1打破了微服务的职责单一性,因为微服务本身是业务模块,它本不应该承担配置刷新的职责。
  • 破坏了微服务各节点的对等性,微服务A会变成一个带头大哥,他出事了微服务集群就没有自动刷新能力,这个锅太大。
  • 有一定的局限性。例如,微服务在迁移时,它的网络地址常常会发生变化,此时如果想要做到自动刷新,那就会增加更多的修改。

四、开始实战-通知所有客户端更新配置(全局广播)

1. 3344配置中心服务端添加消息总线支持

给3344的pom添加消息总线的依赖

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

修改yml配置文件,添加配置,配置上mq的地址账号密码,及bus刷新配置的端点(bus-refresh)
另外注意:配置暴露刷新端点要有actuator依赖,我们工程中已经整合,如果在其他工程使用记得添加上

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

在这里插入图片描述

#rabbitmq相关配置
rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
##rabbitmq相关配置,暴露bus刷新配置的端点
management:
  endpoints: #暴露bus刷新配置的端点
    web:
      exposure:
        include: 'bus-refresh'

2. 3355和3366客户端添加消息总线支持

给3355及3366的pom添加消息总线的依赖

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

修改yml配置文件,添加配置,配置上mq的地址账号密码,上篇已经测试过手动刷新,暴露了刷新接口端点。
在这里插入图片描述

#rabbitmq相关配置
rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest

配置完成后,我们再修改配置文件只需要向3344发送刷新的消息即可完成所有配置了自动刷新的微服务进行刷新。

3. 启动测试

先启动rabitmq,在依次启动7001、3344、3355、3366工程
在这里插入图片描述
然后访问3355、3366的接口获取远端配置信息,查看配置内容

http://localhost:3355/configInfo
http://localhost:3366/configInfo

在这里插入图片描述
接着,修改git仓库中的配置信息内容
在这里插入图片描述
再次访问3355、3366查看配置信息,发现并没有自动变化
接着,我们向3344发送个/bus/refresh消息,通知所有客户端进行更新配置信息,注意:该请求必须为post请求,我这里使用postman进行发送。
postman安装链接:postman安装链接

http://localhost:3344/actuator/bus-refresh

在这里插入图片描述
等待发送完成,再次刷新页面访问3355、3366配置信息
在这里插入图片描述
发现均已发生改变,因此我们成功配置了通知config即可让所有客户端更新。

一次修改,广播通知,处处生效

五、开始实战–通知指定客户端更新配置(定点通知)

只通知3355更新配置,不通知3366更新配置。

1. 修改远程的配置文件

2. 使用消息总线,让3344通知3355服务进行更新

注意:具体的步骤与全局的通知一样,只需要在末尾再加上/服务名:端口号

http://localhost:3344/actuator/bus-refresh/config-client:3355

在这里插入图片描述
这时再分别访问3355和3366,会发现只有3355的配置更新了!


总结

  • 消息总线spring cloud bus可以配合spring cloud config实现动态的刷新。
  • bus可以基于rebitmq或kafka实现。
  • 动态刷新的原理是bus消息总线服务端在rebitmq或kafka上新建一个topic,所有的bus客户端会订阅该主题,然后刷新配置时访问配置中心接口,配置中心通过bus向全部客户端或指定客户端发送消息,从而通知客户端进行配置刷新。
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。