Apache ActiveMQ Artemis 連線路由器允許將傳入的用戶端連線分散到多個目標 Broker。目標 Broker 會被分組到集區中,而連線路由器會使用金鑰,根據政策,從 Broker 集區中選取目標 Broker。

1. 目標 Broker

目標 Broker 是一個可以接受傳入的用戶端連線的 Broker,並且可以是本地或遠端的。本地目標是一個特殊目標,代表託管連線路由器的同一個 Broker。遠端目標是另一個可連線的 Broker。

2. 金鑰

連線路由器會使用金鑰來選取目標 Broker。它是一個從傳入的用戶端連線中擷取的字串,支援的金鑰類型有:

CLIENT_ID

是 JMS 用戶端 ID。

SNI_HOST

是 TLS 通訊協定的 SNI 延伸中,用戶端所指示的主機名稱。

SOURCE_IP

是用戶端的來源 IP 位址。

USER_NAME

是用戶端指示的使用者名稱。

ROLE_NAME

是與連線的已驗證使用者相關聯的角色。

3. 集區

集區是一組目標 Broker,會定期檢查它們的狀態。只有在集區處於作用中狀態時,才會提供已準備好分發傳入用戶端連線的目標 Broker 清單。當符合 quorum-size 參數所定義的最小目標 Broker 數量時,集區就會變成作用中狀態。當集區不是作用中狀態時,它不會提供任何目標,以避免在啟動或重新啟動後出現異常的分散情況。將本地 Broker 包含在目標集區中,也允許託管路由器的 Broker 接受傳入的用戶端連線。預設情況下,集區不包含本地 Broker,若要將其包含為目標,則 local-target-enabled 參數必須為 true。有三種類型的集區:叢集集區探索集區靜態集區

3.1. 叢集集區

叢集集區使用叢集連線來取得要加入的目標 Broker。讓我們看看 broker.xml 中使用叢集連線的叢集集區範例

<pool>
  <cluster-connection>cluster1</cluster-connection>
</pool>

3.2. 探索集區

探索集區使用探索群組來探索要加入的目標 Broker。讓我們看看 broker.xml 中使用探索群組的探索集區範例

<pool>
    <discovery-group-ref discovery-group-name="dg1"/>
</pool>

3.3. 靜態集區

靜態集區使用靜態連接器的清單來定義要加入的目標 Broker。讓我們看看 broker.xml 中使用靜態連接器清單的靜態集區範例

<pool>
    <static-connectors>
        <connector-ref>connector1</connector-ref>
        <connector-ref>connector2</connector-ref>
        <connector-ref>connector3</connector-ref>
    </static-connectors>
</pool>

3.4. 定義集區

集區由 pool 元素定義,其中包含以下項目

  • username 元素定義連線到目標 Broker 的使用者名稱;

  • password 元素定義連線到目標 Broker 的密碼;

  • check-period 元素定義檢查目標 Broker 的頻率,以毫秒為單位,預設值為 5000

  • quorum-size 元素定義啟動集區所需的最小已就緒目標數量,預設值為 1

  • quorum-timeout 元素定義取得最小已就緒目標數量的逾時時間,以毫秒為單位,預設值為 3000

  • local-target-enabled 元素定義集區是否必須包含本地目標,預設值為 false

  • cluster-connection 元素定義 叢集集區使用的叢集連線

  • static-connectors 元素定義 靜態集區使用的靜態連接器清單;

  • discovery-group 元素定義 探索集區使用的探索群組

讓我們看看 broker.xml 中的集區範例

<pool>
    <quorum-size>2</quorum-size>
    <check-period>1000</check-period>
    <local-target-enabled>true</local-target-enabled>
    <static-connectors>
        <connector-ref>connector1</connector-ref>
        <connector-ref>connector2</connector-ref>
        <connector-ref>connector3</connector-ref>
    </static-connectors>
</pool>

4. 政策

政策定義如何從集區中選取 Broker,並允許金鑰值轉換。包含的政策有

FIRST_ELEMENT

從集區中選取第一個已就緒的目標 Broker。它適用於根據其順序定義的優先順序來選取已就緒的目標 Broker,例如,假設有 2 個目標 Broker,此政策僅在第一個目標 Broker 未就緒時選取第二個目標 Broker。

ROUND_ROBIN

從集區中依序選取目標,此政策適用於平均分配;

CONSISTENT_HASH

依金鑰選取目標。此政策總是為相同金鑰選取相同的目標 Broker,直到它從集區中移除為止。

LEAST_CONNECTIONS

選取具有最少作用中連線的目標。此政策可協助您維護與目標 Broker 的作用中連線的平均分配。

CONSISTENT_HASH_MODULO` 將金鑰值轉換為 0 到 N-1 的數字,它會使用單一 `modulo

屬性來設定邊界 N。其中一個使用案例是在 N 個 Broker 的叢集中進行 CLIENT_ID 分割。透過一致性雜湊 % N 轉換,每個用戶端 ID 可以獨佔地對應到其中一個 Broker。

政策由 policy 元素定義。讓我們看看 broker.xml 中的政策範例

<policy name="FIRST_ELEMENT"/>

5. 快取

連線路由器提供具有逾時的快取,以改善所選取目標 Broker 的黏性,只要金鑰值存在於快取中且已就緒,就會傳回相同的目標 Broker。因此,啟用快取的連線路由器不會嚴格遵循設定的政策。預設情況下,快取未啟用。

快取由 cache 元素定義,其中包含以下項目

  • persisted 元素定義快取是否必須保留項目,預設值為 false

  • timeout 元素定義在移除項目之前的逾時時間,以毫秒為單位,設定為 0 將停用逾時,預設值為 0

讓我們看看 broker.xml 中的快取範例

<cache>
  <persisted>true</persisted>
  <timeout>60000</timeout>
</cache>

6. 定義連線路由器

連線路由器由 connection-router 元素定義,其中包含以下項目

  • name 屬性定義連線路由器的名稱,並用於從接收器參考路由器;

  • key-type 元素定義選取目標 Broker 的金鑰類型,支援的值為:CLIENT_IDSNI_HOSTSOURCE_IPUSER_NAMEROLE_NAME,預設值為 SOURCE_IP,詳情請參閱金鑰

  • key-filter 元素定義一個正規表示式,用於篩選已解析的金鑰值

  • local-target-filter 元素定義一個正規表示式,用於比對必須傳回本地目標的金鑰值,如果金鑰的值未定義或與 key-filter 不符,則金鑰值可以等於特殊字串 NULL

  • pool 元素定義要分組目標 Broker 的集區,請參閱集區

  • policy 元素定義用於從集區中選取目標 Broker 的政策,請參閱政策

讓我們看看 broker.xml 中的一些連線路由器範例

<connection-routers>
    <connection-router name="local-partition">
         <key-type>CLIENT_ID</key-type>
         <key-filter>^.{3}</key-filter>
         <local-target-filter>^FOO.*</local-target-filter>
    </connection-router>
    <connection-router name="simple-router">
        <policy name="FIRST_ELEMENT"/>
        <pool>
            <static-connectors>
                <connector-ref>connector1</connector-ref>
                <connector-ref>connector2</connector-ref>
                <connector-ref>connector3</connector-ref>
            </static-connectors>
        </pool>
    </connection-router>
    <connection-router name="consistent-hash-router">
        <key-type>USER_NAME</key-type>
        <local-target-filter>admin</local-target-filter>
        <policy name="CONSISTENT_HASH"/>
        <pool>
            <local-target-enabled>true</local-target-enabled>
            <discovery-group-ref discovery-group-name="dg1"/>
        </pool>
    <policy name="CONSISTENT_HASH"/>
    </connection-router>
    <connection-router name="evenly-balance">
      <key-type>CLIENT_ID</key-type>
      <key-filter>^.{3}</key-filter>
      <policy name="LEAST_CONNECTIONS"/>
      <pool>
        <username>guest</username>
        <password>guest</password>
        <discovery-group-ref discovery-group-name="dg2"/>
      </pool>
    </connection-router>
</connection-routers>

7. 金鑰值

金鑰值是從傳入的用戶端連線擷取的。如果傳入的用戶端連線沒有所使用金鑰類型的值,則金鑰值會設定為特殊字串 NULL。如果傳入的用戶端連線有所使用金鑰類型的值,則可以使用 key-filterpolicy 循序操作擷取的金鑰值。如果定義了 key-filter 且篩選器比對失敗,則值會設定為特殊字串 NULL。如果定義了具有金鑰轉換的 policy,則金鑰值會設定為已轉換的值。

8. 連線路由器工作流程

連線路由器工作流程包含以下步驟

  • 從傳入的連線擷取金鑰值

  • 如果金鑰值符合本地篩選器,則傳回本地目標 Broker;

  • 委派給集區

  • 如果快取中的目標 Broker 已就緒,則傳回快取中的目標 Broker;

  • 從集區取得已就緒/作用中的目標 Broker;

  • 使用政策選取一個目標 Broker;

  • 將選取的 Broker 新增到快取

  • 傳回選取的 Broker。

讓我們看看連線路由器工作流程的流程圖:連線路由器工作流程

9. 資料重力

第一個路由器設定:local-partition,示範最簡單的使用案例,也就是透過將應用程式資料的子集限制到特定 Broker 來保留 資料重力。每個 Broker 都會獲得一組它將獨佔服務或拒絕的金鑰子集。如果 Broker 位於循環配置負載平衡器之後或完全了解 Broker URL,則 Broker 最終會回應。local-target-filter 正規表示式決定最適合為您的應用程式保留 資料重力 的分割粒度。

挑戰在於在所有相關的應用程式連線中提供一致的金鑰

資料重力 的概念嘗試捕捉現實,也就是說,雖然位址由多個應用程式共用,但最好將相關的位址及其資料共置於單一 Broker 上。一般而言,應用程式應該 連線 到資料,而不是將資料移動到應用程式連線的任何 Broker。當資料量 (積壓) 很大時,追隨消費者的移動成本會超過傳遞到應用程式的成本,這一點尤其如此。有了「資料重力」的心態,營運人員會較不關心連線數量,而更關心應用程式及其需要互動的位址。

10. 重新導向

Apache ActiveMQ Artemis 為支援的客戶端提供原生重新導向功能,並為其他客戶端提供新的管理 API。原生重新導向可以針對每個接收器啟用,且僅支援 AMQP、CORE 和 OPENWIRE 客戶端。帶有 router URL 參數的接收器會重新導向傳入的連線。 router URL 參數指定要使用的連線路由器名稱,例如,以下接收器將使用名為 simple-router 的連線路由器重新導向傳入的 CORE 客戶端連線。

<acceptor name="artemis">tcp://0.0.0.0:61616?router=simple-router;protocols=CORE</acceptor>

10.1. 原生重新導向順序

支援原生重新導向的客戶端會連線至啟用重新導向的接收器。接收器會將要重新導向的目標代理發送給客戶端 (如果目標代理已就緒),然後關閉連線。客戶端如果先前已收到目標代理的資訊,則會連線至該目標代理,否則會再次連線至啟用重新導向的接收器。

Native Redirect Sequence

10.2. 管理 API 重新導向順序

不支援原生重新導向的客戶端會查詢連線路由器的管理 API,以取得要重新導向的目標代理。如果 API 回傳目標代理,客戶端就會連線至該代理,否則客戶端會再次查詢 API。

Management API Redirect Sequence