1. 程式人生 > >Spring Cloud Bus 分散式系統的節點與輕量級訊息代理連結

Spring Cloud Bus 分散式系統的節點與輕量級訊息代理連結

Spring Cloud Bus

Spring Cloud Bus將分散式系統的節點與輕量級訊息代理連結。這可以用於廣播狀態更改(例如配置更改)或其他管理指令。一個關鍵的想法是,匯流排就像一個分散式執行器,用於擴充套件的Spring Boot應用程式,但也可以用作應用程式之間的通訊通道。目前唯一的實現是使用AMQP代理作為傳輸,但是相同的基本功能集(還有一些取決於傳輸)在其他傳輸的路線圖上。

注意 Spring Cloud根據非限制性Apache 2.0許可證釋出。如果您想為文件的這一部分做出貢獻,或者發現錯誤,請在github中找到專案中的原始碼和問題跟蹤器。

快速開始

Spring Cloud Bus的工作原理是新增Spring Boot自動配置,如果它在類路徑中檢測到自身。所有您需要做的是啟用匯流排是將spring-cloud-starter-bus-amqp

spring-cloud-starter-bus-kafka新增到您的依賴關係管理中,並且Spring Cloud負責其餘部分。確保代理(RabbitMQ或Kafka)可用和配置:在本地主機上執行,??您不應該做任何事情,但如果您遠端執行使用Spring Cloud聯結器或Spring Boot定義經紀人憑據的約定,例如Rabbit

application.yml

spring:
  rabbitmq:
    host: mybroker.com
    port: 5672
    username: user
    password: secret

匯流排當前支援向所有節點發送訊息,用於特定服務的所有節點(由Eureka定義)。未來可能會新增更多的選擇器標準(即,僅資料中心Y中的服務X節點等)。/bus/*

執行器名稱空間下還有一些http端點。目前有兩個實施。第一個/bus/env傳送金鑰/值對來更新每個節點的Spring環境。第二個,/bus/refresh,將重新載入每個應用程式的配置,就好像他們在他們的/refresh端點上都被ping過。

注意 匯流排起動器覆蓋了Rabbit和Kafka,因為這是兩種最常用的實現方式,但是Spring Cloud Stream非常靈活,繫結器將與spring-cloud-bus結合使用。

處理例項

HTTP端點接受“目的地”引數,例如“/ bus / refresh?destination = customers:9000”,其中目的地是ApplicationContext

ID。如果ID由總線上的一個例項擁有,那麼它將處理訊息,所有其他例項將忽略它。Spring Boot將ContextIdApplicationContextInitializer中的ID設定為spring.application.name,活動配置檔案和server.port的組合。

定址服務的所有例項

“destination”引數用於Spring PathMatcher(路徑分隔符為冒號:)以確定例項是否處理該訊息。使用上述示例,“/ bus / refresh?destination = customers:**”將針對“客戶”服務的所有例項,而不管配置檔案和埠設定為ApplicationContext ID。

應用程式上下文ID必須是唯一的

匯流排嘗試從原始ApplicationEvent一次消除處理事件兩次,一次從佇列中消除。為此,它會檢查傳送應用程式上下文id,以重新顯示當前的應用程式上下文ID。如果服務的多個例項具有相同的應用程式上下文id,則不會處理事件。在本地機器上執行,每個服務將在不同的埠上,這將是應用程式上下文ID的一部分。Cloud Foundry提供了區分的索引。要確保應用程式上下文ID是唯一的,請將spring.application.index設定為服務的每個例項唯一的值。例如,在lattice中,在application.properties中設定spring.application.index=${INSTANCE_INDEX}(如果使用configserver,請設定bootstrap.properties)。

自定義Message Broker

Spring Cloud Bus使用 Spring Cloud Stream廣播訊息,以便獲取訊息流,只需要在類路徑中包含您選擇的binder實現。有AMQP(RabbitMQ)和Kafka(spring-cloud-starter-bus-[amqp,kafka])的公共汽車專用起動方便。一般來說,Spring Cloud Stream依賴於用於配置中介軟體的Spring Boot自動配置約定,因此例如AMQP代理地址可以使用spring.rabbitmq.配置屬性更改。Spring Cloud Bus在spring.cloud.bus.中具有少量本地配置屬性(例如spring.cloud.bus.destination是使用外部中介軟體的主題的名稱)。通常,預設值就足夠了。

要更多地瞭解如何自定義訊息代理設定,請參閱Spring Cloud Stream文件。

跟蹤Bus Events

可以通過設定spring.cloud.bus.trace.enabled=true來跟蹤匯流排事件(RemoteApplicationEvent的子類)。如果這樣做,那麼Spring Boot TraceRepository(如果存在)將顯示每個傳送的事件和來自每個服務例項的所有ack。示例(來自/trace端點):

{
  "timestamp": "2015-11-26T10:24:44.411+0000",
  "info": {
    "signal": "spring.cloud.bus.ack",
    "type": "RefreshRemoteApplicationEvent",
    "id": "c4d374b7-58ea-4928-a312-31984def293b",
    "origin": "stores:8081",
    "destination": "*:**"
  }
  },
  {
  "timestamp": "2015-11-26T10:24:41.864+0000",
  "info": {
    "signal": "spring.cloud.bus.sent",
    "type": "RefreshRemoteApplicationEvent",
    "id": "c4d374b7-58ea-4928-a312-31984def293b",
    "origin": "customers:9000",
    "destination": "*:**"
  }
  },
  {
  "timestamp": "2015-11-26T10:24:41.862+0000",
  "info": {
    "signal": "spring.cloud.bus.ack",
    "type": "RefreshRemoteApplicationEvent",
    "id": "c4d374b7-58ea-4928-a312-31984def293b",
    "origin": "customers:9000",
    "destination": "*:**"
  }
}

該跟蹤顯示RefreshRemoteApplicationEventcustomers:9000傳送到所有服務,並且已被customers:9000stores:8081收到(acked)。

為了處理訊號,您可以向您的應用新增AckRemoteApplicationEventSentApplicationEvent型別的@EventListener(並啟用跟蹤)。或者您可以利用TraceRepository並從中挖掘資料。

注意 任何匯流排應用程式都可以跟蹤ack,但有時在一個可以對資料進行更復雜查詢的中央伺服器中執行此操作是有用的。或者將其轉發到專門的跟蹤服務。

廣播自己的Events

匯流排可以攜帶任何型別為RemoteApplicationEvent的事件,但預設傳輸是JSON,並且解串器需要知道哪些型別將提前使用。要註冊一個新型別,它需要在org.springframework.cloud.bus.event的子包中。

要自定義事件名稱,您可以在自定義類上使用@JsonTypeName,或者依賴預設策略來使用類的簡單名稱。請注意,生產者和消費者都需要訪問類定義。

在自定義包中註冊事件

如果您不能或不想為自定義事件使用org.springframework.cloud.bus.event的子包,則必須使用@RemoteApplicationEventScan指定要掃描型別為RemoteApplicationEvent的事件的包。使用@RemoteApplicationEventScan指定的軟體包包括子包。

例如,如果您有一個名為FooEvent的自定義事件:

package com.acme;

public class FooEvent extends RemoteApplicationEvent {
    ...
}

您可以通過以下方式與解串器註冊此事件:

package com.acme;

@Configuration
@RemoteApplicationEventScan
public class BusConfiguration {
    ...
}

沒有指定一個值,使用@RemoteApplicationEventScan的類的包將被註冊。在這個例子中,com.acme將使用BusConfiguration的包進行註冊。

您還可以使用@RemoteApplicationEventScan上的valuebasePackagesbasePackageClasses屬性明確指定要掃描的軟體包。例如:

package com.acme;

@Configuration
//@RemoteApplicationEventScan({"com.acme", "foo.bar"})
//@RemoteApplicationEventScan(basePackages = {"com.acme", "foo.bar", "fizz.buzz"})
@RemoteApplicationEventScan(basePackageClasses = BusConfiguration.class)
public class BusConfiguration {
    ...
}

以上@RemoteApplicationEventScan的所有示例都是等效的,因為com.acme程式包將通過在@RemoteApplicationEventScan上明確指定程式包來註冊。請注意,您可以指定要掃描的多個基本軟體包。

歡迎關注作者的公眾號《Java程式設計生活》,每日記載Java程式猿工作中遇到的問題 在這裡插入圖片描述