Bus了解与使用

简介

       Spring Cloud Bus 将轻量级消息代理程序链接到分布式系统的节点。然后可以使用此代理来广播状态更改(例如配置更改)或其他管理指令。一个关键的想法是,总线就像是横向扩展的 Spring Boot 应用程序的分布式执行器。但是,它也可以用作应用之间的通信渠道。该项目为 AMQP 经纪人或 Kafka 提供了入门服务。

官网: https://cloud.spring.io/spring-cloud-bus/reference/html/

Spring Cloud Bus 配合 Spring Cloud Config 使用可以实现配置的动态刷新!

Spring Cloud Bus 支持两种消息代理:RabbinMQ 和 Kafka

在这里插入图片描述

根据上图可知,在某个时候改变了 git 仓库中的某个数据之后,3344 会直接去获得最新数据,然后再由一个中间件给我们自动的提交命令来进行数据刷新,在之后就是由拿到最新数据的那个服务来对其他服务进行传播。

Bus能干嘛?

Spring Cloud Bus 能管理和传播分布式系统间的消息,就像一个分布式执行器,可用于广播状态更改、事件推送等,也可以当做微服务间的通信通道

在这里插入图片描述

这个图的效果和刚才的图片效果是不同的,刚才那个是先传播给一个服务,然后在由被传播的服务再次传播给其他服务;当这个图片是直接传给了 Config Server(3344),然后在有 Config Server 一次性传播给所有服务!

消息总线

       在微服务架构的系统中,通常会使用轻量级的消息代理来构建一个共用的消息主题,并让系统中所有微服务实例都连接上来。由于该主题中产生的消息会被所有实例监听和消费,所以称它为 “消息总线”。在总线上的各个实例,都可以方便的广播一些需要让其它连接在该主题上的实例都知道的消息。

基本原理

       CloudClient 实例都监听 MQ 中同一个 topic(默认是 SpringCloudBus)。 当一个服务刷新数据的时候,它会把这个信息放入到 Topic 中,这样其它监听同一 Topic 的服务就能得到通知,然后去更新自身的配置。

RabbitMQ 环境配置

Erlang 安装

下载地址: http://erlang.org/download/otp_win64_21.3.exe

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

基本就是傻瓜式安装,但是要注意的是安装的位置一定不要是中文目录下,否则尽可能会出现一些不必要的问题!

安装好后我们来配置环境变量(我这里配置在系统变量中,系统变量和用户变量没有太大的区别)

在这里插入图片描述

新建一个环境变量,名为 ERLANG_HOME,然后内容为 Erlang 的安装位置

在这里插入图片描述

然后在 Path 中新建两个变量,分别是 Erlang 的 bin 目录和刚才创建好的变量

RabbitMQ安裝

下载地址http://dl.bintray.com/rabbitmq/all/rabbitmq-server/3.7.14/rabbitmq-server-3.7.14.exe

其实说白了这两个软件都是傻瓜式安装,一直下一步即可

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

虽然是傻瓜式安装,但是还是有一些要求的!

  1. 电脑用户名不能是中文,就算自己通过简单的方式进行修改了也是没用的,特别是用了家庭版系统的兄弟,因为家庭版一旦是中文用户名就无法在进行修改了!!!

    解决方案: https://blog.csdn.net/wls666/article/details/103334152

  2. 安装目录不能有中文(这个解决方案就是把软件删除然后在放进一个英文目录下)

在 RabbitMQ 的 sbin 目录下打开命令行页面,输入以下命令启动管理功能

rabbitmq-plugins enable rabbitmq_management

在这里插入图片描述

启动后我们就可以在开始菜单栏看到多了以下几个东西

在这里插入图片描述

查看是否安装成功

点击 RabbitMQ Service - start 启动 RabbitMQ

在这里插入图片描述

然后在浏览器中访问 15672 端口(15672是RabbitMQ的默认端口号)

在这里插入图片描述

如果启动正常,那么显示的就是 RabbitMQ 的主页,然后默认的账号密码都是 guest

在这里插入图片描述

如果出现以下效果,那么就说明已经安装成功了

在这里插入图片描述

动态刷新全局广播的设计思想和选型

上面我们已经配置好了 RabbitMQ 的环境,接下来就可以开始使用了

新建一个名为 cloud-config-client-3366 的子工程

修改 pom 文件

<?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">
    <parent>
        <artifactId>SpringCloud2020</artifactId>
        <groupId>com.lyang.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-config-client-3366</artifactId>

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

        <!-- 引入自己定义的api通用包,可以使用 Payment 支付 Entity -->
        <dependency>
            <groupId>com.lyang.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>compile</scope>
        </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>
</project>

编写 bootstrap.yml 文件

server:
  port: 3355

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

# 服务注册到 Eureka 地址
eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka

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

编写启动类

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

编写业务类

/**
 * @RefreshScope:帮助我们做局部的参数刷新
 */
@RestController
@RefreshScope
@Slf4j
public class ConfigClientController {
    @Value("${server.port}")
    private String serverPort;

    @Value("${config.info}")
    private String configInfo;

    @GetMapping("/configInfo")
    public String getConfigInfo() {
        return "serverPort:" + serverPort + "\t\n\n configInfo: " + configInfo;
    }
}

测试

启动顺序:7001–3344–3366

在这里插入图片描述

到此和之前3355没有什么区别,接下来我们在来进行调整

设计思想

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

    缺点:

    ① 打破了微服务的职责单一性,因为微服务本身是业务模块,它本不应该承担刷新职责

    ② 破坏了微服务各个节点的对等性

    ③ 有一定的局限性,比如微服务在迁移时,它的网络地址常常会发生变化,此时如果想要做到自动刷新,那就会增加更多的修改

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

Bus 动态刷新全局广播配置实现

修改3344、3355、3366

在这三个服务的 pom 文件中添加以下依赖

<!-- 添加消息总线 RabbitMQ 支持 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>

修改 3344 的 yml 文件

server:
  port: 3344

spring:
  application:
    # 注册进 eureka 服务器的微服务名
    name: cloud-config-center
  cloud:
    config:
      server:
        git:
          # 自己的 github 仓库地址
          uri: https://github.com/T257ymq/spring-cloud-config.git
          # 搜索目录
          search-paths:
            - springcloud-config
      # 读取分支
      label: master
  # RabbitMQ 相关配置-----新增部分
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest

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

# RabbitMQ 相关配置,暴露 bus 刷新配置的端点-----新增部分
management:
  # 暴露 bus 刷新配置的端点
  endpoints:
    web:
      exposure:
        include: 'bus-refresh'

修改 3355 的 yml 文件

server:
  port: 3355

spring:
  application:
    name: config-client
  cloud:
    # Config 客户端配置
    config:
      # 分支名称
      label: master
      # 配置文件名称
      name: config
      # 读取后缀名称
      # 上述3个综合:master 分支上 config-dev.yml的配置文件被读取http://config-3344.com:3344/master/config-dev.yaml
      profile: dev
      # 配置中心地址
      uri: http://localhost:3344
  # rabbitmq 相关配,15672是Web管理界面的端口,5672是 MQ 访问的端口-----新增部分
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest

# 服务注册到 Eureka 地址
eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka

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

修改 3366 的 yml 文件

server:
  port: 3366

spring:
  application:
    name: config-client
  cloud:
    # Config 客户端配置
    config:
      # 分支名称
      label: master
      # 配置文件名称
      name: config
      # 读取后缀名称
      # 上述3个综合:master 分支上 config-dev.yml的配置文件被读取http://config-3344.com:3344/master/config-dev.yaml
      profile: dev
      # 配置中心地址
      uri: http://localhost:3344
  # rabbitmq 相关配,15672是Web管理界面的端口,5672是 MQ 访问的端口-----新增部分
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest

# 服务注册到 Eureka 地址
eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka

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

测试

启动顺序:7001–3344–3355–3366

然后先在浏览器中测试3344、3355、3366 和 Eureka,效果如下

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

现在以上服务都可以正常访问,那么我们再来修改 git 仓库上 dev 中的数据

在这里插入图片描述

接下来就有运维工程师发送 POST 请求给 3344(客户端),由客户端一次性传播给所有的服务端

打开命令行页面输入以下命令来提交 POST 请求

curl -X POST "http://localhost:3344/actuator/bus-refresh"

在这里插入图片描述

此处完成后没有任何提示那么就是已经执行完了,在之前的测试当中,我们是一个服务一个服务的去进行传播的,而现在是使用客户端的方式一次性传播给所有的服务端,接下来我们再来测试一下,看看是不是所有的服务端都获取到了最新的数据!

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

我们可以发现,之前是对指定服务端提交 POST 请求后才可以获得最新数据,但是这样增加了很多的工作量!因为需要对每一个服务端都提交一次!

我们现在使用客户端的方式,只需要在客户端提交 POST 请求即可让所有的服务获取到最新的数据!

在之前我们在基本原理中也说过了,“ConfigClient 实例都监听 MQ 中同一个 topic(默认是 springCloudBus)”,我们可以登录 RabbitMQ 来进行查看订阅主题,只要是被订阅到的,就可以被广播通知!

在这里插入图片描述

就好比一个微信公众号,当很多人关注了这个公众号后,公众号发布一个内容后关注的人都可以接收到。

这个时候我们就达到了 “一次修改,广播通知,处处生效”

Bus 动态刷新定点通知

有时候我们只想通知指定的服务,而其他的服务并不通知,那么就可以使用定点通知的方式。

简单来说,就是指具体某一个实例生效而不是全部!

公式:http://localhost:配置中心的端口号/actuator/bus-refresh/{destiation}

案例

接下来就来做一个只通知 3355 而不通知 3366 的操作

不需要修改任何的代码,先修改 git 仓库中 dev 环境的版本,然后运维工程式把命令换成顶点刷新的格式即可

修改dev版本

在这里插入图片描述

修改后输入以下命令提交 POST 请求

curl -X POST "http://localhost:3344/actuator/bus-refresh/config-client:3355"

config-client 是服务名称(对应 yml 文件中的)

测试
3344
在这里插入图片描述

3355
在这里插入图片描述

3366
在这里插入图片描述

由此可见,我们已经成功实现了定点刷新,只有我们指定了的服务能够获取到最新的数据,而没有被指定的服务则获取不到最新的数据

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值