SpringCloud之消息總線

前面的話】書接上文SpringCloud之Config,若是沒有看過能夠先移步去看一下。在上一篇文章中提到了配置刷新的問題,若是須要刷新配置就須要客戶端執行refresh,咱們能夠利用webhook的機制每次提交代碼發送請求來刷新客戶端,當客戶端愈來愈多的時候,須要每一個客戶端都執行一遍,這種方案就不太適合了。使用Spring Cloud Bus能夠完美解決這一問題。git


壹、Spring Cloud Bus的簡介

Spring cloud bus經過輕量消息代理鏈接各個分佈的節點。這會用在廣播狀態的變化(例如配置變化)或者其餘的消息指令。Spring bus的一個核心思想是經過分佈式的啓動器對spring boot應用進行擴展,也能夠用來創建一個多個應用之間的通訊頻道。目前惟一實現的方式是用AMQP消息代理做爲通道,一樣特性的設置(有些取決於通道的設置)在更多通道的文檔中。github

貳、解決方案

方案一:

  • Spring cloud bus被國內不少都翻譯爲消息總線,也挺形象的。你們能夠將它理解爲管理和傳播全部分佈式項目中的消息既可,其實本質是利用了MQ的廣播機制在分佈式的系統中傳播消息,目前經常使用的有Kafka和RabbitMQ。利用bus的機制能夠作不少的事情,其中配置中心客戶端刷新就是典型的應用場景之一,咱們用一張圖來描述bus在配置中心使用的機制。

方案一流程圖

根據此圖咱們能夠看出利用Spring Cloud Bus作配置更新的步驟:web

一、提交代碼觸發post給客戶端A發送/actuator/bus-refresh
    二、客戶端A接收到請求從Server端更新配置而且發送給Spring Cloud Bus
    三、Spring Cloud bus接到消息並通知給其它客戶端
    四、其它客戶端接收到通知,請求Server端獲取最新配置
    五、所有客戶端均獲取到最新的配置

方案二:

  • 在方案一中咱們已經到達了利用消息總線觸發一個客戶端/actuator/bus-refresh,而刷新全部客戶端的配置的目的。但這種方式並不優雅。緣由以下:
打破了微服務的職責單一性。微服務自己是業務模塊,它本不該該承擔配置刷新的職責。
   破壞了微服務各節點的對等性。
   有必定的侷限性。例如,微服務在遷移時,它的網絡地址經常會發生變化,此時若是想要作到自動刷新,那就不得不修改WebHook的配置。

所以咱們將方案一的架構模式稍微改變一下spring

方案二流程圖

這時Spring Cloud Bus作配置更新步驟以下:bootstrap

一、提交代碼觸發post請求給bus/refresh
  二、server端接收到請求併發送給Spring Cloud Bus
  三、Spring Cloud bus接到消息並通知給其它客戶端
  四、其它客戶端接收到通知,請求Server端獲取最新配置
  五、所有客戶端均獲取到最新的配置

下面咱們就採用方案二來改造咱們的工程,這樣的話咱們在server端的代碼作一些改動,來支持bus/refreshapi

叄、改造服務端

  • 改造上文的config的服務端子工程lovin-config-server,添加RabbitMQ的依賴。下面是改造後的主要的pom依賴:
<parent>
        <artifactId>lovincloud</artifactId>
        <groupId>com.eelve.lovincloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>lovin-config-server</artifactId>
    <packaging>jar</packaging>
    <name>lovinconfigserver</name>
    <version>0.0.1</version>
    <description>配置服務端</description>

    <dependencies>
        <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-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-starter-client</artifactId>
            <version>2.1.6</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
  • 添加rabbitmq的鏈接配置
server:
  port: 8886   # 服務端口號
spring:
  application:
    name: lovinconfigserver     # 服務名稱
  security:
    basic:
      enabled: true
    user:
      name: lovin
      password: ${REGISTRY_SERVER_PASSWORD:lovin}
  cloud:
    config:
      server:
        git:
          uri: https://github.com/lovinstudio/lovincloud
          search-paths: lovin-config-repo
      label: master
  rabbitmq:
    host: 127.0.0.1
    port: 5672
    username: guest
    password: guest
eureka:
  client:
    serviceUrl:
      defaultZone: http://lovin:lovin@localhost:8881/eureka/   # 註冊到的eureka服務地址

肆、改造配置客戶端

  • 改造上文的config的服務端子工程lovin-config-client,添加RabbitMQ的依賴。下面是改造後的主要的pom依賴:
<parent>
        <artifactId>lovincloud</artifactId>
        <groupId>com.eelve.lovincloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>lovin-config-client</artifactId>
    <packaging>jar</packaging>
    <name>lovinconfigclient</name>
    <version>0.0.1</version>
    <description>配置消費端</description>

    <dependencies>
        <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-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-starter-client</artifactId>
            <version>2.1.6</version>
        </dependency>
<!--        <dependency>-->
<!--            <groupId>org.springframework.cloud</groupId>-->
<!--            <artifactId>spring-cloud-config-server</artifactId>-->
<!--        </dependency>-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
            <version>2.1.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
  • 添加鏈接rabbitmq的相關配置
  1. 修改bootstrap.yml添加鏈接rabbitmq的配置
server:
  port: 8807   # 服務端口號
spring:
  application:
    name: lovinconfigclient     # 服務名稱
  security:
    basic:
      enabled: true
    user:
      name: lovin
      password: ${REGISTRY_SERVER_PASSWORD:lovin}
#eureka:
#  client:
#    serviceUrl:
#      defaultZone: http://lovin:lovin@localhost:8881/eureka/   # 註冊到的eureka服務地址
  rabbitmq:
    host: 127.0.0.1
    port: 5672
    username: guest
    password: guest
  1. 修改application.yml開啓消息跟蹤
spring:
  cloud:
    config:
      name: lovin-config
      profile: dev
      #uri: http://localhost:8886/
      #label: master
      discovery:
        enabled: true
        service-id: lovinconfigserver
    bus:
      trace:
        enabled: true
eureka:
  client:
    serviceUrl:
      defaultZone: http://lovin:lovin@localhost:8881/eureka/   # 注意在高可用的時候須要見註冊中心配置移到該文件中,在application.yml中見會讀取不到配置

伍、啓動測試

  • 1.首先依次啓動lovin-eureka-server、lovin-econfig-server、lovin-econfig-client
  • 2.查看lovin-econfig-server查詢配置

查看lovin-econfig-server查詢配置

  • 3.查看lovin-econfig-client查詢配置

查看lovin-econfig-client查詢配置

  • 4.修改配置,並提交見token的值由lovin改成lovinupdate

修改token

  • 5.再次查看lovin-econfig-server查詢配置

再次查詢服務端

  • 6.再次查看lovin-econfig-client查詢配置

再次查詢客戶端

  • 7.刷新消息總線
    因爲api變動,url由老版本的/bus/refresh變爲actuator/bus-refresh

屬性消息總線

  • 8.再次查看lovin-econfig-client查詢配置

再次查看客戶端配置

咱們能夠看到已經刷新成功,至此消息總線配置已經完成網絡

陸、局部刷新

某些場景下(例如灰度發佈),咱們可能只想刷新部分微服務的配置,此時可經過/actuator/bus-refresh端點的destination參數來定位要刷新的應用程序。架構

  • 例如:/actuator/bus-refresh?destination=customers:8000,這樣消息總線上的微服務實例就會根據destination參數的值來判斷是否須要要刷新。其中,customers:8000指的是各個微服務的ApplicationContext ID。destination參數也能夠用來定位特定的微服務。
  • 例如:/actuator/bus-refresh?destination=customers:**,這樣就能夠觸發customers微服務全部實例的配置刷新。

相關文章
相關標籤/搜索