代理程式網路

功能 > 叢集 > 代理程式網路

為了提供大型訊息架構的大規模可擴展性,您通常會希望將多個代理程式連接成一個網路,以便擁有任意數量的用戶端邏輯上連接在一起 - 並根據您的用戶端數量和網路拓撲結構,運行所需數量的訊息代理程式。

如果您使用客戶端/伺服器或中心/輻射型拓撲,那麼您連接的代理程式會成為單點故障,這也是需要代理程式網路(或叢集)的另一個原因,這樣您才能在任何特定代理程式、機器或子網路故障時倖存下來。

從 ActiveMQ Classic 1.1 版開始,支援代理程式網路,這讓我們可以支援跨代理程式網路的分散式佇列和主題

這允許用戶端連線到網路中的任何代理程式 - 如果發生故障,則故障轉移到另一個代理程式 - 從用戶端的角度來看,提供了一個高可用性代理程式叢集。

注意: 預設情況下,網路連線是單向的 - 建立連線的代理程式會將訊息傳遞到其連線的代理程式。從 ActiveMQ Classic 5.x 版本開始,可以選擇啟用網路連線為雙向,這對於中心和輻射型架構非常有用,在這種架構中,中心位於防火牆後方等等。

設定代理程式網路

設定代理程式網路最簡單的方法是透過Xml 設定。建立代理程式網路主要有兩種方法

  • 使用硬式編碼的 networkConnector 元素清單。

  • 使用探索來偵測代理程式(多點傳送或會合)。

使用固定 URI 清單的範例

以下是使用固定 URI 清單的範例

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://activemq.org/config/1.0">

  <broker brokerName="receiver" persistent="false" useJmx="false">  
    <networkConnectors>
      <networkConnector uri="static:(tcp://127.0.0.1:62001)"/>
    </networkConnectors>

    <persistenceAdapter>
      <memoryPersistenceAdapter/>
    </persistenceAdapter>

   <transportConnectors>
      <transportConnector uri="tcp://127.0.0.1:62002"/>
    </transportConnectors>
  </broker>

</beans>

ActiveMQ Classic 也支援除了 tcp 之外的其他傳輸協定,例如用於網路連接器的 http。

使用多點傳送探索的範例

此範例使用多點傳送探索

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://activemq.org/config/1.0">

  <broker name="sender" persistent="false" useJmx="false">  
    <networkConnectors>
      <networkConnector uri="multicast://default"/>
    </networkConnectors>

    <persistenceAdapter>
      <memoryPersistenceAdapter/>
    </persistenceAdapter>

  <transportConnectors>
      <transportConnector uri="tcp://127.0.0.1:0" discoveryUri="multicast://default"/>
    </transportConnectors>
  </broker>

</beans>

啟動網路連接器

預設情況下,網路連接器會作為代理程式啟動順序的一部分依序啟動。當某些網路速度較慢時,它們會阻止其他網路及時啟動。5.5 版支援代理程式屬性 networkConnectorStartAsync=”true”,這將導致代理程式使用執行器並行啟動網路連接器,與代理程式啟動非同步。

靜態探索

透過static: 探索,您可以硬式編碼代理程式 URL 清單。將會為每個 URL 建立一個網路連接器。

<networkConnectors>
  <networkConnector uri="static:(tcp://host1:61616,tcp://host2:61616,tcp://..)"/>
</networkConnectors>

您可以在靜態網路連接器上設定一些有用的屬性,以進行重試

屬性 預設值 描述
initialReconnectDelay 1000 嘗試重新連線之前等待的時間 (ms)(如果 useExponentialBackOff 為 false)
maxReconnectDelay 30000 嘗試重新連線之前等待的時間 (ms)
useExponentialBackOff true 在重新連線序列中,每次失敗時都會增加重新連線之間的時間
backOffMultiplier 2 如果使用指數退避,則用於增加等待時間的乘數

例如:

uri="static:(tcp://host1:61616,tcp://host2:61616)?maxReconnectDelay=5000&useExponentialBackOff=false"

主從探索

代理程式網路的常見設定選項是在代理程式和 n+1 個代理程式配對(主/從)之間建立網路橋接。典型的設定包括使用 failover: 傳輸協定,但還有一些非直觀的選項必須設定才能按預期運作。因此,ActiveMQ Classic v5.6+ 有一個方便的探索代理程式,可以使用 masterslave: 傳輸協定前置詞指定

<networkConnectors>
  <networkConnector uri="masterslave:(tcp://host1:61616,tcp://host2:61616,tcp://..)"/>
</networkConnectors>

URI 的順序為:MASTER,SLAVE1,SLAVE2…SLAVE(不讚同)

static: 的相同設定選項適用於 masterslave:

NetworkConnector 屬性

屬性 預設值 描述
名稱 橋接 網路的名稱 - 若在同一兩個代理程式之間有多個網路連接器,請使用不同的名稱
dynamicOnly false 如果為 true,則只有當對應的持久訂閱重新啟動時才啟用網路化的持久訂閱,預設情況下,它們會在啟動時啟用。
decreaseNetworkConsumerPriority true 如果為 true,則從優先順序 -5 開始,針對從生產者開始(在網路躍點中)距離越遠的網路佇列消費者,降低傳送的優先順序。如果為 false,所有網路消費者都使用與本機消費者相同的預設優先順序 (0)(在 v5.18.0 之前,預設值為 false)
networkTTL 1 網路中訊息和訂閱可以通過的代理程式數量(設定訊息和消費者 TTL)
messageTTL 1 (5.9 版)訊息可以在網路中通過的代理程式數量
consumerTTL 1 (5.9 版)訂閱可以在網路中通過的代理程式數量(在網狀網路中保持為 1)
conduitSubscriptions true 訂閱相同目的地的多個消費者會被網路視為一個消費者
excludedDestinations 與此清單比對的目的地將不會在網路之間轉發(這僅適用於 dynamicallyIncludedDestinations)
dynamicallyIncludedDestinations 與此清單比對的目的地將會在網路之間轉發 注意: 空清單表示將轉發所有不在 excluded 清單中的目的地
useVirtualDestSubs false 如果為 true,網路連線將會接聽虛擬目的地消費者的諮詢訊息
staticallyIncludedDestinations 符合條件的目的地將始終在網路之間傳遞 - 即使從未有消費者註冊過此興趣
duplex false 如果為 true,網路連線將會用於生產取用訊息。這對於中心和輻射型情境非常有用,在這些情境中,中心位於防火牆後方等等。
prefetchSize 1000 設定網路連接器消費者上的預取大小。它必須 > 0,因為網路消費者不會輪詢訊息
suppressDuplicateQueueSubscriptions false (從 5.3 版開始)如果為 true,則將會抑制網路中由網路中介產生的重複訂閱。例如,假設透過多點傳送探索連線網路的代理程式 A、B 和 C。A 上的消費者會在 B 和 C 上產生網路消費者。此外,C 將連線到 B(基於 A 的網路消費者),B 將連線到 C。如果為 true,則將抑制 C 和 B 之間的網路橋接(是其現有對 A 的網路訂閱的副本)。當生產者或消費者在網路上遷移時,以這種方式減少路由選擇可提供決定性,因為消除了死路由(卡住的訊息)的可能性。networkTTL 需要比對或超過代理程式計數才能要求此介入。
bridgeTempDestinations true 是否在代理程式網路中廣播有關建立的暫時目的地的諮詢訊息。暫時目的地通常是為請求-回覆訊息建立的。預設會開啟廣播有關暫時目的地的資訊,以便請求-回覆訊息的消費者可以連接到網路中的另一個代理程式,並仍然在 JMSReplyTo 標頭中指定的暫時目的地傳回回覆。在大多數/所有訊息都使用請求-回覆模式的應用程式情境中,這會在代理程式網路上產生額外的流量,因為每個訊息通常都會設定唯一的 JMSReplyTo 位址(這會導致在代理程式網路中透過諮詢訊息建立並廣播新的暫時目的地)。停用此功能後,可以減少此類網路流量,但是請求-回覆訊息的生產者和消費者需要連線到同一代理程式。遠端消費者(即透過您網路中的另一個代理程式連線)將無法傳送回覆訊息,而是會引發「暫時目的地不存在」的例外。
alwaysSyncSend false (5.6 版)如果為 true,則使用請求/回覆而不是單向將非持久性訊息傳送到遠端代理程式。此設定會將持久性和非持久性訊息視為相同。
staticBridge false (5.6 版)如果設定為 true,代理程式將不會動態回應新的消費者。它只會使用 staticallyIncludedDestinations 來建立需求訂閱
userName null 用來針對遠端代理程式進行驗證的使用者名稱
password null 用來針對遠端代理程式進行驗證的使用者名稱密碼

可靠性

代理程式網路會可靠地儲存和轉發訊息。如果來源是持久的,佇列或持久主題訂閱上的持久性訊息,網路將保留持久性保證。
但是,當來源是非持久性時,網路無法新增持久性。根據定義,非持久性主題訂閱和暫時目的地(佇列和主題)是非持久性的。當非持久性
來源連網時,如果發生故障,正在傳輸的訊息可能會遺失。

排序

代理程式網路不會保留訊息的總排序。總排序適用於單一消費者,但 networkBridge 會引入第二個消費者。此外,網路橋接消費者透過 producer.send(..) 轉發訊息,因此它們會從轉發代理程式上的佇列開頭移至目標上的佇列結尾。如果單一消費者在網路代理程式之間移動,則如果所有訊息始終遵循消費者,則可能會保留總排序,但是這很難保證有大量訊息待辦事項。

何時使用和不使用通道訂閱

ActiveMQ Classic 依賴關於活動消費者(訂閱)的資訊,以便在網路中傳遞訊息。代理程式會以處理本機客戶端連線訂閱的方式,解讀來自遠端(網路)代理程式的訂閱,並將任何相關訊息的副本路由到每個訂閱。對於主題訂閱和多個遠端訂閱,遠端代理程式會將每個訊息副本解讀為有效,因此當它將訊息路由到自己的本機連線時,會發生重複訊息。因此,預設的導管行為會整合所有符合的訂閱資訊,以防止重複訊息在網路中流動。使用此預設行為,遠端代理程式上的 N 個訂閱看起來就像網路代理程式的一個訂閱。

然而,如果您僅使用佇列,重複訂閱是一項有用的功能。由於負載平衡演算法會嘗試均勻地分配訊息負載,只有在標記 conduitSubscriptions=false 的情況下,跨網路的消費者才會均等分享訊息負載。以下是一個範例。假設您有兩個代理程式 A 和 B,它們透過轉送橋接器彼此連線。連線到代理程式 A,您有一個消費者訂閱名為 Q.TEST 的佇列。連線到代理程式 B,您有兩個消費者也訂閱 Q.TEST。所有消費者的優先順序都相同。然後,您在代理程式 A 上啟動一個生產者,將 30 條訊息寫入 Q.TEST。依預設(conduitSubscriptions=true),15 條訊息將傳送到代理程式 A 上的消費者,而其餘 15 條訊息將傳送到代理程式 B 上的兩個消費者。訊息負載並未平均分散到所有三個消費者,因為依預設,代理程式 A 將代理程式 B 上的兩個訂閱視為一個。如果您將 conduitSubscriptions 設定為 false,則三個消費者中的每一個都會收到 10 條訊息。

雙工網路連接器

預設情況下,網路橋接器會在單一連線上按需單向轉送訊息。當 duplex=true 時,相同的連線會用於相反方向的網路橋接器,從而產生雙向橋接器。網路橋接器組態會傳播到另一個代理程式,因此雙工橋接器是原始橋接器的精確複本。

給定兩個代理程式,代理程式 A 和代理程式 B,在 A 到 B 上的雙工橋接器與在 A 到 B 上的預設橋接器以及在 B 到 A 上的預設橋接器相同。

請注意,如果您想要在兩個代理程式之間設定多個雙工網路橋接器,以提高輸送量或分割主題和佇列,您必須為每個橋接器提供唯一的名稱

<networkConnectors>
        <networkConnector name="SYSTEM1" duplex="true" uri="static:(tcp://10.x.x.x:61616)">
                <dynamicallyIncludedDestinations>
                        <topic physicalName="outgoing.System1" />
                </dynamicallyIncludedDestinations>
        </networkConnector>
        <networkConnector name="SYSTEM2" duplex="true" uri="static:(tcp://10.x.x.x:61616)">
                <dynamicallyIncludedDestinations>
                        <topic physicalName="outgoing.System2"/>
                </dynamicallyIncludedDestinations>
        </networkConnector>
  </networkConnectors>

導管訂閱和消費者選擇器

導管訂閱會忽略本機代理程式上的消費者選擇器,並將所有訊息傳送到遠端代理程式。然後,在將訊息分派給消費者之前,會在遠端代理程式上剖析選擇器。此概念可能會在使用多代理程式網路中,使用選擇器在佇列上取用訊息時產生一些問題。想像一下,當您有一個生產者代理程式將訊息轉送到兩個接收代理程式,且這兩個代理程式各自有一個具有不同選擇器的消費者時。由於在生產者代理程式端未評估任何選擇器,您最終可能會讓所有訊息都只傳送到其中一個代理程式,因此具有特定屬性的訊息將不會被取用。如果您需要支援此使用案例,請關閉 conduitSubscription 功能。

組態陷阱

如果停用了 advisorySupport 代理程式屬性,網路將無法如預期般運作(它們無法動態回應新的消費者)。如果停用了 advisorySupport,則僅能選擇完全靜態設定的網路。請在以下章節中閱讀更多相關資訊。

代理程式和通知網路

代理程式網路嚴重依賴通知訊息,因為它們會在幕後用於表達對遠端新消費者的興趣。依預設,當網路連接器啟動時,它會在以下主題上定義一個消費者 ActiveMQ.Advisory.Consumer.>(暫時忽略暫時目的地)。如此一來,當消費者連線(或中斷連線)到遠端代理程式時,本機代理程式將收到通知,並將其視為必須處理的另一個消費者。

這在小型網路和具有少量目的地和消費者的環境中都很好。但是,隨著事情開始增長,預設模型(監聽所有內容、分享所有內容)將無法很好地擴展。這就是為什麼您可以使用許多方式來篩選將在代理程式之間分享的目的地。

動態網路

讓我們從動態設定的網路開始。這表示我們只想要在遠端有消費者時,將訊息傳送到遠端代理程式。如果我們想要將此行為限制在某些目的地,我們將使用 dynamicallyIncludedDestinations,例如

<networkConnector uri="static:(tcp://host)">
  <dynamicallyIncludedDestinations>
    <queue physicalName="include.test.foo"/>
    <topic physicalName="include.test.bar"/>
  </dynamicallyIncludedDestinations>
</networkConnector>

在 ActiveMQ Classic 5.6 之前的版本中,代理程式仍會使用相同的通知篩選器,並表達對遠端代理程式上所有消費者的興趣。實際的篩選將在訊息分派期間完成。這在大型網路中不是最佳解決方案,因為它會產生大量的「通知」流量和代理程式上的負載。從 5.6 版開始,代理程式將自動建立適當的通知篩選器,並且只對動態包含的目的地表達興趣。針對我們的範例,它將是「ActiveMQ.Advisory.Consumer.Queue.include.test.foo,ActiveMQ.Advisory.Consumer.Topic.include.test.bar」。這可以顯著改善複雜和高負載環境中網路的行為。

在較舊的代理程式版本中,我們可以透過稍微複雜的設定來實現相同的目標。控制我們對哪些消費者感興趣的實際通知篩選器,是透過 destinationFilter 連接器屬性定義的。其預設值為「>」,該值會串連到 "ActiveMQ.Advisory.Consumer." 前綴。因此,若要達到相同的目的,我們需要執行以下操作

<networkConnector uri="static:(tcp://host)" destinationFilter="Queue.include.test.foo,ActiveMQ.Advisory.Consumer.Topic.include.test.bar">
  <dynamicallyIncludedDestinations>
    <queue physicalName="include.test.foo"/>
    <topic physicalName="include.test.bar"/>
  </dynamicallyIncludedDestinations>
</networkConnector>

請注意,第一個目的地沒有前綴,因為它是隱含的。設定和維護起來有點複雜,但它會有效。而且如果您使用的是 5.6 或更新版本的代理程式,只需使用 dynamicallyIncludedDestinations 包含所需的目的地就足夠了。

這也說明了為什麼如果您關閉代理程式上的通知支援,動態網路將無法運作。在這種情況下,代理程式無法動態回應新的消費者。

純靜態網路

如果您希望完全保護代理程式免受遠端代理程式上任何消費者的影響,或者如果您希望將代理程式用作簡單的 Proxy,並將所有訊息轉送到遠端,而不管是否有消費者,則應考慮靜態網路。

<networkConnector uri="static:(tcp://host)" staticBridge="true">
        <staticallyIncludedDestinations>
      		<queue physicalName="always.include.queue"/>
        </staticallyIncludedDestinations>
</networkConnector>

staticBridge 參數從 5.6 版開始提供,這表示本機代理程式不會訂閱遠端代理程式上的任何通知主題,這表示它不關心是否有任何消費者。此外,您需要在 staticallyIncludedDestinations 中新增目的地清單。這將產生與在目的地上有其他消費者的效果相同,因此訊息也會轉送到遠端代理程式。由於在較早版本的 ActiveMQ Classic 中沒有 staticBridge 參數,因此您可以透過將 destinationFilter 設定為監聽未使用的通知主題來欺騙代理程式,例如

<networkConnector uri="static:(tcp://host)" destinationFilter="NO_DESTINATION">
        <staticallyIncludedDestinations>
      		<queue physicalName="always.include.queue"/>
        </staticallyIncludedDestinations>
</networkConnector>

如果像這樣設定,代理程式將嘗試監聽 ActiveMQ.Advisory.Consumer.NO_DESTINATION 上的新消費者,該主題永遠不會有訊息,因此它將受到遠端代理程式消費者資訊的保護。

動態網路和虛擬目的地(5.13.0 版新增)

如上所述,可以將代理程式網路設定為僅在包含的目的地上有消費者時,才將訊息傳送到遠端代理程式。但是,讓我們考慮一下使用虛擬目的地時,動態流程如何發生的一些情況。

虛擬目的地消費者和複合目的地

以下是一個將兩個代理程式網路連線在一起的範例。本機代理程式包含設定有 dynamicallyIncludedDestination 的網路連接器,而遠端代理程式則設定有 CompositeTopic

本機代理程式

<networkConnector uri="static:(tcp://host)">
	<dynamicallyIncludedDestinations>
    	<topic physicalName="include.bar"/>
	</dynamicallyIncludedDestinations>
</networkConnector>

遠端代理程式

<compositeTopic name="include.bar" forwardOnly="false">
    <forwardTo>
        <queue physicalName="include.bar.forward" />
    </forwardTo>
</compositeTopic >

在此範例中,讓我們考慮遠端代理程式上佇列 include.bar.forward 上的一個消費者。如果將訊息直接傳送到遠端代理程式上的主題 include.bar,它將會轉送到佇列 include.bar.forward,而消費者將會收到它。但是,如果將訊息發佈到本機代理程式上的相同主題,則此訊息將不會轉送到遠端代理程式。

訊息未轉送,因為佇列 include.bar.forward 上的消費者不會在本機代理程式中被偵測為 dynamicallyIncludedDestinations 清單的一部分。除非在原始主題上也有消費者(在此範例中為 include.bar),否則訊息不會轉送到遠端代理程式。您可以透過將本機代理程式設定為監聽虛擬目的地訂閱來解決此問題。

首先,我們需要將遠端代理程式設定為在消費者訂閱符合虛擬目的地的目的地時傳送通知訊息。在此情況下,內部會透過使用目的地篩選器來判斷比對,該篩選器會判斷一個目的地是否會轉送到另一個目的地。若要啟用此功能,請將遠端代理程式上的屬性 useVirtualDestSubs 設定為 true

遠端代理程式

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://activemq.org/config/1.0">

  <broker name="remoteBroker" useVirtualDestSubs="true">  
     .....
  </broker>

</beans>

接下來,需要設定本機代理程式上的網路連接器,以透過將 useVirtualDestSubs 屬性設定為 true 來監聽新的通知訊息

本機代理程式

<networkConnector uri="static:(tcp://host)" useVirtualDestSubs="true">
  <dynamicallyIncludedDestinations>
    <topic physicalName="include.bar"/>
  </dynamicallyIncludedDestinations>
</networkConnector>

現在,如果消費者在遠端代理程式上訂閱佇列 include.bar.forward,本機代理程式將會轉送傳送到主題 include.bar 的訊息。

在目的地建立時的虛擬目的地消費者

現在,讓我們考慮上述使用案例,其中有相同的複合主題,但佇列上沒有消費者。
  遠端代理程式

<compositeTopic name="include.bar" forwardOnly="false">
    <forwardTo>
        <queue physicalName="include.bar.forward" />
    </forwardTo>
</compositeTopic >

遠端代理程式上設定了複合主題,而本機代理程式則與其連線。

即使我們已啟用 useVirtualDestSubs,除非消費者訂閱轉送的佇列,否則訊息將不會轉送到遠端代理程式。如果沒有消費者,訊息將會被丟棄,因為它們會傳送到本機代理程式上的主題 (include.bar)。在這種情況下,希望根據轉送到下列項目的虛擬目的地的存在情況來轉送訊息

  • 一個或多個佇列;或
  • 具有持久訂閱的主題。

儘管這些目的地上沒有活動的消費者,這兩種情況都被視為發出對本機代理程式的訊息需求。

遠端代理程式

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://activemq.org/config/1.0">

  <broker name="remoteBroker" useVirtualDestSubs="true" useVirtualDestSubsOnCreation="true">  
     .....
  </broker>

</beans>

透過此設定,當佇列 include.bar.forward 被建立時,將會傳送一個虛擬目的地消費者通知給本地 Broker,使其知道要根據轉發到佇列的複合主題的存在來轉發訊息。

複合目的地消費者和虛擬主題

以上範例展示了如何設定複合目的地,但虛擬主題也同樣適用。在以下範例中,遠端 Broker 上虛擬主題佇列的消費者現在將會引起需求,並且訊息將會從本地 Broker 透過網路傳送。

本機代理程式

<networkConnector uri="static:(tcp://host)">
  <dynamicallyIncludedDestinations>
    <topic physicalName="VirtualTopic.>"/>
  </dynamicallyIncludedDestinations>
</networkConnector>

遠端代理程式

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://activemq.org/config/1.0">

  <broker name="remoteBroker" useVirtualDestSubs="true" >  
     .....
  </broker>

</beans>

使用 NetworkConnector 屬性的範例設定

以下是 Broker 設定範例的一部分

<networkConnectors>
      <networkConnector uri="static:(tcp://127.0.0.1:61617)"
         name="bridge"
         conduitSubscriptions="true"
         decreaseNetworkConsumerPriority="false">
      	<dynamicallyIncludedDestinations>
      		<queue physicalName="include.test.foo"/>
      		<topic physicalName="include.test.bar"/>
      	</dynamicallyIncludedDestinations>
      	<excludedDestinations>
      		<queue physicalName="exclude.test.foo"/>
      		<topic physicalName="exclude.test.bar"/>
      	</excludedDestinations>
        <staticallyIncludedDestinations>
      		<queue physicalName="always.include.queue"/>
      		<topic physicalName="always.include.topic"/>
      	</staticallyIncludedDestinations>
      </networkConnector>
    </networkConnectors>

請注意,目前 excludedDestinations 屬性不會影響 staticallyIncludedDestinations

在兩個 Broker 之間可以有多個網路連接器。每個網路連接器使用一個底層傳輸連接,因此您可能希望這樣做來提高吞吐量,或擁有更靈活的設定。

例如,如果使用分散式佇列,您可能希望在網路中對佇列接收器進行等權重處理,但只有在接收器處於活動狀態時才執行 - 例如。

<networkConnectors>
      <networkConnector uri="static:(tcp://127.0.0.1:61617)"
         name="queues_only"
         conduitSubscriptions="false"
         decreaseNetworkConsumerPriority="false">
      	<excludedDestinations>
      		<topic physicalName=">"/>
      	</excludedDestinations>
      </networkConnector>
    </networkConnectors>

注意: 您只能在 excludedDestinationsdynamicallyIncludedDestinations 屬性中使用萬用字元
注意: 如果您在網路上使用持久主題訂閱者,請勿更改橋接器的名稱或 Broker 的名稱。ActiveMQ Classic 內部使用網路名稱和 Broker 名稱來為網路建立一個獨特但可重複的持久訂閱者名稱。

卡住的訊息

卡住的訊息可能有多種原因,以下章節旨在提供有助於解決此問題的設定建議。

停用 replayWhenNoConsumers (版本 5.6)

有一個目的地策略允許佇列的這種行為,方法是使用 replayWhenNoConsumers=true 設定 conditionalNetworkBridgeFilterFactoryconditionalNetworkBridgeFilterFactory 提供一個基於 broker-in 時間的可選 replayDelay

    <destinationPolicy>
      <policyMap>
        <policyEntries>
          <policyEntry queue="TEST.>" enableAudit="false">
            <networkBridgeFilterFactory>
              <conditionalNetworkBridgeFilterFactory replayWhenNoConsumers="true"/>
            </networkBridgeFilterFactory>
          </policyEntry>
        </policyEntries>
      </policyMap>
    </destinationPolicy>

注意: 當對版本 < 5.9 使用 replayWhenNoConsumers=true 時,還必須使用 enableAudit=false 停用游標重複偵測,因為游標可能會將重新傳送的訊息標記為重複(取決於透過網路橋接器播放和重新播放這些訊息之間的時間間隔)。此問題在這篇部落格文章中完整說明。

啟用 decreaseNetworkConsumerPriority

在 networkConnector 中設定 decreaseNetworkConsumerPriority="true" 以限制通知數量,並優先選擇本地消費者。(更多資訊請參閱 AMQ-7316

<networkConnectors>
  <networkConnector uri="static:(tcp://mybroker:61616)" decreaseNetworkConsumerPriority="true" />
</networkConnectors>

如果您使用訊息群組和消費者池,請增加 prefetchsize

如果啟用了訊息群組,則一個群組可能會阻止佇列的複製(如果此群組中的訊息大小大於設定的 prefetchsize),提供足夠的 prefetchSize 以確保所有消費者執行緒可以消耗其分配的群組。

增加 TTL

網路 Broker 的 TTL 設定(networkTTL、messageTTL 和 consumerTTL)應足夠高,以便在消費者多次來回故障的情況下允許訊息在 Broker 之間交換數次。

節流網路消費者

conditionalNetworkBridgeFilterFactory 工廠允許為目的地指定速率限制,以便可以節流網路消費者。網路消費者的預取在很大程度上被網路消費者通常非常快速地轉發訊息的事實所否定,因此即使具有較低的預取和降低的優先順序,網路消費者也可能會讓速度適中的本地消費者處於飢餓狀態。節流為此提供了解決方案。

Apache、ActiveMQ、Apache ActiveMQ、Apache 羽毛標誌和 Apache ActiveMQ 專案標誌是 The Apache Software Foundation 的商標。版權所有 © 2024,The Apache Software Foundation。根據 Apache License 2.0 授權。