SpringCloud系列之(十)服务总线

服务总线

一、SpringCloud Bus 消息总线

Bus是对Config的加强

解决的问题:全局通知与定点通知

局域网广播型的通知离不开消息中间件

1. 概述

实现分布式自动刷新配置功能,Spring Cloud Bus配合Spring Cloud Config使用可以实现配置的动态刷新

1.1 是什么

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

  1. Github上的配置更新
  2. Config Server获取到更新
  3. Cloud Bus提交刷新配置的POST请求给App A
  4. a:App A发送消息给Cloud Bus
  5. a:Cloud Bus广播到其他微服务

Spring Cloud Bus是用来将分布式系统的节点与轻量级消息系统链接起来的框架,
它整合了Java的事件处理机制和消息中间件的功能。

Bus支持两种消息代理:RabbitMQ和Kafka

1.2 能干嘛

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

1.3 为何被称为总线

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

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

https://www.bilbili.com/video/av55976700?from=search&seid=15010075915728605208

一句话总结:SpringCloud与RabbitMQ或Kafka整合完成了事件监听、通知的功能

2. RabbitMQ环境配置

参考Windows 工具使用指南.md 二十八、RabbitMQ

3. SpringCloud Bus动态刷新全局广播

3.1 构建cloud-config-client-3366

  • 建Module【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>cloud2020</artifactId>
            <groupId>com.atguigu.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>
            <dependency>
                <groupId>com.atguigu.springcloud</groupId>
                <artifactId>cloud-api-commons</artifactId>
                <version>${project.version}</version>
            </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: 3366
    
    spring:
      application:
        name: config-client
      cloud:
        # Config客户端配置
        config:
          # 分支名称
          label: main
          # 服务名
          name: application
          # 环境
          profile: dev
          # Config服务端地址
          uri: http://localhost:3344
          # 上述配置含义:加载http://localhost:3344/main/application-dev.yml配置内容到客户端本地
    eureka:
      client:
        service-url:
          defaultZone: http://eureka7001.com: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;
    
    @EnableEurekaClient
    @SpringBootApplication
    public class ConfigClientMain3366 {
        public static void main(String[] args) {
            SpringApplication.run(ConfigClientMain3366.class, args);
        }
    }
    
  • 业务类

    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;
    
    @RestController
    @RefreshScope
    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;
    }
    

    }

    
    
    
    
    

3.2 设计思想

从技术角度能够实现的两种设计思想如下:

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

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

设计思想选型

第二种设计思想更加合适,第一种设计思想不适合的原因如下

  • 打破了微服务的职责单一性,因为微服务本身是业务模块,它本不应该承担配置刷新职责
  • 破坏了微服务各节点的对等性【选中的微服务处于某一业务的微服务集群中的情况下】
  • 有一定的局限性。例如,微服务在迁移时,它的网络地址常常会发生变化,此时如果想要做到自动刷新,那就会增加更多的修改

3.3 给cloud-config-center-3344配置中心服务端添加消息总线支持

  • 修改POM,添加如下依赖

    <!--添加消息总线RabbitMQ支持-->
    <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>
    
  • 修改application.yml,添加如下配置

    # RabbitMQ相关配置
    spring:
      rabbitmq:
        host: localhost
        port: 5672
        username: guest
        password: guest
      
    # 以下配置需要org.springframework.boot.spring-boot-starter-actuator包的支持  
    # RabbitMQ相关配置,暴露bus刷新配置的端点
    management:
      endpoints:
        web:
          exposure:
            include: 'bus-refresh'
    

3.4 给cloud-config-center-3355客户端添加消息总线支持

  • 修改POM,添加如下依赖

    <!--添加消息总线RabbitMQ支持-->
    <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>
    
  • 修改bootstrap.yml,添加如下配置

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

3.5 给cloud-config-center-3366客户端添加消息总线支持

  • 修改POM,添加如下依赖

    <!--添加消息总线RabbitMQ支持-->
    <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>
    
  • 修改bootstrap.yml,添加如下配置

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

3.6 测试

启动EurekaMain7001

启动cloud-config-center-3344

启动cloud-config-client-3355

启动cloud-config-client-3366

修改Github上配置文件的内容

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

执行上述命令后,从RabbitMQ的web管理界面能够看到发送了消息

访问http://localhost:3355/configInfo和http://localhost:3366/configInfo,获取配置信息,发现都已经刷新了

至此,实现了SpringCloud Bus动态刷新全局广播

4. SpringCloud Bus动态刷新定点通知

​ 指定具体某一个实例生效而不是全部都生效,不想全部通知,只想定点通知,比如只通知3355,不通知3366

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

/bus/refresh请求发给config server并通过destination参数类指定需要更新配置的服务或实例

destination参数的格式为:${spring.application.name}:${server.port}

以修改配置后只更新3355不更新3366为例:

Github上配置文件修改后执行curl -X POST "http://localhost:3344/actuator/bus-refresh/config-client:3355"

总结

posted @   刘二水  阅读(283)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示