大聪明教你学Spring Cloud核心组件 | 第五篇:消息总线(SpringCloud Bus)

4,819 阅读5分钟

前言

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情

咱们书接上文,在上一章中我们简单的聊了聊SpringCloud的配置中心(大聪明教你学Spring Cloud核心组件 | 第四篇:配置中心(Config)),说完了配置中心以后,可能会有一些小伙伴产生了疑问:那如果我有一百个项目的话,修改一次配置文件岂不是要请求一百次刷新地址?那这时候我们就该有请SpringCloud中的消息总线(Spring Cloud Bus)闪亮登场了。

什么是SpringCloud Bus

首先还是先简单说说什么是Spring Cloud Bus。

Spring cloud bus通过轻量消息代理连接各个分布的节点。会用在广播状态的变化(例如配置变化)或者其他的消息指令。Spring bus的一个核心思想是通过分布式的启动器对spring boot应用进行扩展,也可以用来建立一个多个应用之间的通信频道。目前唯一实现的方式是用AMQP消息代理作为通道。

大家可以将它理解为管理和传播所有分布式项目中的消息既可,其实本质是利用了MQ的广播机制在分布式的系统中传播消息,目前常用的有Kafka和RabbitMQ。

那么在本文中,我们选择使用Kafka(搭建启动kafka的步骤百度上有很多,这里就不再多说了),通过Kafka来讲解一下如合使用Spring Cloud Bus实现广播配置文件的变化。

整合SpringCloud Bus

我们打开上一节中搭建的两个项目,分别是config-serve和config-client,然后对他们进行一个小小的改造。

首先修改一下config-serve项目,我们需要在它的pom.xml文件中增加几个依赖,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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.springboot</groupId>
    <artifactId>config-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>config-server</name>
    <description>Demo project for springboot config</description>
    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-cloud.version>Hoxton.SR10</spring-cloud.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

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

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>

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

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

        <!--SpingBoot 服务监控 帮助你在应用程序生产环境时监视和管理应用程序。可以使用HTTP的各种请求来监管,审计,收集应用的运行情况-->
        <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>

然后我们再修改一下application.yml配置文件,我们需要在application.yml中增加一些关于kafka的相关设置

server:
  port: 8012
spring:
  application:
    name: config-server
  cloud:
    config:
      server:
        git:
          uri: https://gitee.com/trs_sjz/springcloud-config
          username: XXXXXX
          password: XXXXXX
          basedir: D:\springcloudconfig\gitee
          search-paths: config-cloud
    # kafka
    stream:
      kafka:
        binder:
          brokers: localhost:9092   #kafka地址
          zk-nodes: localhost:2181	#zookeeper地址
          auto-create-topics: true
    bus:
      trace:
        enabled: true
      enabled: true
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8081/eureka/
# 客户端调用需要
management:
  endpoints:
    web:
      exposure:
        include: bus-refresh
  security:
    enabled: false

同样的,我们也要对config-client进行相同的改造,下面直接贴代码

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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.springboot</groupId>
    <artifactId>config-client</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>config-client</name>
    <description>Demo project for config-client</description>
    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-cloud.version>Hoxton.SR10</spring-cloud.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

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

        <!-- spring cloud config 客户端包 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>

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

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.10</version>
        </dependency>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</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>

application.yml文件

server:
  port: 3302
management:
  endpoints:
    web:
      exposure:
        include: bus-refresh
data:
  env: NaN
  user:
    username: NaN
    password: NaN

bootstrap.yml文件

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8081/eureka/
spring:
  profiles:
    active: dev
---
spring:
  profiles: prod
  application:
    name: ziye
  cloud:
    config:
      uri: http://localhost:8012
      label: master
      profile: prod
    # kafka
    stream:
      kafka:
        binder:
          brokers: localhost:9092
          zk-nodes: localhost:2181
          auto-create-topics: true
    bus:
      trace:
        enabled: true
---
spring:
  profiles: dev
  application:
    name: ziye
  cloud:
    config:
      uri: http://localhost:8012
      label: master
      profile: dev
    # kafka
    stream:
      kafka:
        binder:
          brokers: localhost:9092
          zk-nodes: localhost:2181
          auto-create-topics: true
    bus:
      trace:
        enabled: true

为了模拟多个项目,我们再复制一个config-client2项目(config-client2与config-client的配置相同,config-client2所用端口为3303),然后我们分别启动config-client、config-client2、config-server以及Eureka-Server服务注册中心 ==(千万别忘了启动kafka)==。

在这里插入图片描述 在这里插入图片描述

项目启动成功后,我们首先来访问一下http://localhost:8012/ziye-dev.yml和http://localhost:8012/ziye-prod.yml,我们可以看到页面返回了配置文件的内容。 在这里插入图片描述 在这里插入图片描述 然后我们再去访问一下http://localhost:3302/autoShow和http://localhost:3303/autoShow2地址(为了区分config-client和config-client2,让二者请求不同的配置文件,config-client请求ziye-dev.yml,config-client2请求ziye-prod.yml)。 我们可以看到页面也正常返回了配置文件中的信息。 在这里插入图片描述 在这里插入图片描述那么接下来我们对gitee上的配置文件进行一个小小的修改,修改后我们可以直接刷新上面提到的四个地址,这时候我们会发现通过config-server请求的两个地址所展示的信息已经被更新了,变成了修改后的配置信息;而通过http://localhost:3302/autoShow和http://localhost:3303/autoShow2请求所展示的配置信息并没有更新。 在这里插入图片描述 在这里插入图片描述 此时我们就需要请求一下http://localhost:8012/actuator/bus-refresh地址来刷新一下了,==这里需要注意的是请求一定是POST请求(可以通过Postman来进行请求)==

P.S. 如果我们不希望刷新全部客户端的话,我们可以用下面的方式进行刷新http://localhost:8012/actuator/bus-refresh/客户端名:客户端口号(端口号可用*来代替) 在这里插入图片描述 请求成功后,我们再分别访问一下http://localhost:3302/autoShow和http://localhost:3303/autoShow2地址,我们就发现此时获取到了最新的配置文件信息。 在这里插入图片描述 在这里插入图片描述 有了上面的讲解,我相信各位小伙伴应该能很快的理解下面这张图了 在这里插入图片描述 根据此图我们可以很容易的总结出利用Spring Cloud Bus做配置更新的步骤:

  1. 提交代码触发post给客户端A发送/actuator/bus-refresh
  2. 客户端A接收到请求从Server端更新配置并且发送给Spring Cloud Bus
  3. Spring Cloud bus接到消息并通知给其它客户端
  4. 其它客户端接收到通知,请求Server端获取最新配置
  5. 全部客户端均获取到最新的配置

结语

微服务一般都采用集群方式部署,而且在高并发下经常需要对服务进行扩容、缩容、上线、下线的操作。比如我们需要更新配置,又或者需要同时失效所有服务器上的某个缓存,需要向所有相关的服务器发送命令,此时就可以选择使用Spring Cloud Bus了。其实说的再简单点就是,在我们需要把一个操作散发到所有后端相关服务器的时候,我们的首选就是Spring Cloud Bus ,借用一句广告语来说就是:自从用了消息总线,我的腰不疼了,腿不痛了,一口气管理一千个服务也不费劲了。

本人经验有限,有些地方可能讲的没有特别到位,如果您在阅读的时候想到了什么问题,欢迎在评论区留言,我们后续再一一探讨🙇‍

希望各位小伙伴动动自己可爱的小手,来一波点赞+关注 (✿◡‿◡) 让更多小伙伴看到这篇文章~ 蟹蟹呦(●'◡'●)

如果文章中有错误,欢迎大家留言指正;若您有更好、更独到的理解,欢迎您在留言区留下您的宝贵想法。

爱你所爱 行你所行 听从你心 无问东西