流量控制用於限制客戶端和伺服器之間,或伺服器和另一個伺服器之間資料的流動,以防止客戶端或伺服器被資料淹沒。

1. 消費者流量控制

這控制了伺服器和客戶端之間資料的流動,因為客戶端會消費訊息。為了效能考量,客戶端通常會先緩衝訊息,然後透過 receive() 方法或透過訊息監聽器以非同步方式傳遞給消費者。如果消費者的處理訊息速度不及訊息的傳遞和儲存在內部緩衝區的速度,那麼最終可能會導致訊息不斷累積,如果無法及時處理,則可能會導致客戶端記憶體不足。

1.1. 基於視窗的流量控制

預設情況下,Apache ActiveMQ Artemis 消費者會在客戶端緩衝區中緩衝來自伺服器的訊息,然後客戶端再消費這些訊息。這可以提高效能:否則,每次客戶端消費訊息時,Apache ActiveMQ Artemis 都必須前往伺服器請求下一個訊息。反過來說,如果有的話,這個訊息隨後會被發送到客戶端。

每個訊息都會涉及網路往返,並且會大幅降低效能。

為了防止這種情況發生,Apache ActiveMQ Artemis 會預先將訊息提取到每個消費者的緩衝區中。每個消費者緩衝的訊息總最大大小(以位元組為單位)由 consumerWindowSize 參數決定。

預設情況下,consumerWindowSize 設定為 1 MiB (1024 * 1024 位元組),除非透過 (位址設定) 覆寫。

該值可以是

  • -1 表示無界限的緩衝區

  • 0 表示不緩衝任何訊息。

  • >0 表示具有指定最大大小(以位元組為單位)的緩衝區。

設定消費者視窗大小可以根據訊息傳遞的使用案例大幅提高效能。舉例來說,讓我們考慮兩個極端情況

1.1.1. 快速消費者

快速消費者可以以與消費速度一樣快的速度(甚至更快)處理訊息

為了允許快速消費者,請將 consumerWindowSize 設定為 -1。這將允許客戶端進行無界限的訊息緩衝。

謹慎使用此設定:如果消費者無法以接收訊息的速度處理訊息,則可能會導致客戶端記憶體溢位。

1.1.2. 慢速消費者

慢速消費者需要花費大量時間來處理每個訊息,而且最好不要在客戶端緩衝訊息,以便將訊息傳遞給其他消費者。

考慮這樣的情況:一個佇列有 2 個消費者;其中 1 個速度非常慢。訊息會以循環方式傳遞給這兩個消費者,快速消費者會非常快速地處理完所有訊息,直到其緩衝區為空。此時,慢速消費者的緩衝區中仍有等待處理的訊息,因此無法讓快速消費者處理。因此,快速消費者會閒置,而實際上它可以處理其他訊息。

為了允許慢速消費者,請將 URI 上的 consumerWindowSize 設定為 0(完全不緩衝)。這將防止慢速消費者在客戶端緩衝任何訊息。訊息將保留在伺服器端,以便讓其他消費者消費。

將此設定為 0 可以在佇列上的多個消費者之間提供確定性的分配。

大多數消費者無法明確識別為快速消費者或慢速消費者,而是介於兩者之間。在這種情況下,設定 consumerWindowSize 的值以最佳化效能取決於訊息傳遞的使用案例,並且需要進行基準測試才能找到最佳值,但在大多數情況下,1MiB 的值就足夠了。

請參閱範例章節,其中提供了一個範例,說明如何設定 ActiveMQ Artemis,以在處理慢速消費者時防止消費者緩衝。

1.2. 速率限制流量控制

也可以控制消費者消費訊息的速率。這是一種節流形式,可以用於確保消費者永遠不會以快於指定速率的速度消費訊息。這是使用 consumerMaxRate URI 參數設定的。

速率必須是正整數才能啟用此功能,並且是以每秒訊息為單位指定的最大所需訊息消費速率。將此設定為 -1 會停用速率限制流量控制。預設值為 -1

請參閱範例章節,其中提供了一個限制消費者速率的實際範例。

速率限制流量控制可以與基於視窗的流量控制結合使用。速率限制流量控制只會影響客戶端在一秒內可以消費多少訊息,而不會影響其緩衝區中有多少訊息。因此,如果您有較慢的速率限制和較高的基於視窗的限制,客戶端的內部緩衝區很快就會填滿訊息。

2. 生產者流量控制

Apache ActiveMQ Artemis 也可以限制從客戶端傳送到伺服器的資料量,以防止伺服器不堪重負。

2.1. 基於視窗的流量控制

與消費者基於視窗的流量控制類似,預設情況下,Apache ActiveMQ Artemis 生產者只能將訊息傳送到位址,只要它們有足夠的配額可以這樣做。傳送訊息所需的配額量由訊息的大小決定。

當生產者的配額不足時,它們會向伺服器請求更多配額,當伺服器向它們傳送更多配額時,它們就可以傳送更多訊息。

生產者一次請求的配額量稱為視窗大小,它由 producerWindowSize URI 參數控制。

因此,視窗大小決定了在需要請求更多配額之前,可以在任何時間點處於傳輸中的位元組數量,這可以防止遠端連線超載。

2.1.1. 封鎖 CORE 生產者

當使用 CORE 協定(Artemis Core 用戶端和 Artemis JMS 用戶端都使用)時,伺服器始終會盡力提供與已請求的配額數量相同的配額數量。但是,也可以在任何位址上設定最大大小,並且伺服器永遠不會向任何一個生產者傳送比根據位址的記憶體上限可用的配額更多的配額。儘管單一生產者將會被發出比可用配額更多的配額(在發出時),但有可能有多個生產者與同一個位址相關聯,因此從理論上講,跨所有生產者分配的配額總數可能比可用配額更多。因此,有可能超出位址限制約

total number of producers on address * producer window size

例如,如果我有一個名為「myqueue」的佇列,我可以將最大記憶體大小設定為 10MiB,並且伺服器會控制傳送到任何正在將任何訊息傳送到 myqueue 的生產者的配額數量,以使佇列中的訊息總數永遠不會超過 10MiB。

當位址已滿時,生產者會在客戶端遭到封鎖,直到位址上有更多空間釋出為止,也就是說,直到從佇列中消費訊息,從而釋出空間以傳送更多訊息。

我們稱之為封鎖生產者流量控制,這是一種有效的方法,可以防止伺服器由於生產者傳送的訊息多於任何時候可處理的訊息而導致記憶體不足。

這是分頁的替代方法,分頁不會封鎖生產者,而是將訊息分頁到儲存裝置。

若要設定具有最大大小的位址,並告知伺服器,如果您想要在該位址已滿時封鎖該位址的生產者,您需要為該位址定義 AddressSettings (透過位址設定設定佇列) 區塊,並指定 max-size-bytesaddress-full-policy

位址區塊適用於所有向該位址註冊的佇列。也就是說,繫結到該位址的所有佇列的總記憶體不會超過 max-size-bytes。對於 JMS 主題,這表示主題中所有訂閱的記憶體不會超過 max-size-bytes。

以下為範例

<address-settings>
   <address-setting match="exampleQueue">
      <max-size-bytes>100000</max-size-bytes>
      <address-full-policy>BLOCK</address-full-policy>
   </address-setting>
</address-settings>

上面的範例會將「exampleQueue」佇列的最大大小設定為 100000 個位元組,並且會封鎖任何傳送到該位址的生產者,以防止超出最大大小。

請注意,必須將原則設定為 BLOCK 才能啟用封鎖生產者流量控制。

請注意,在預設設定中,所有位址都設定為在位址中有 10 MiB 的訊息資料後封鎖生產者。這表示您無法向位址傳送超過 10MiB 的訊息資料,而無需先將其消費,然後生產者才會遭到封鎖。如果您不希望出現這種行為,請增加 max-size-bytes 參數或變更位址完整訊息原則。

生產者配額是從代理程式分配給用戶端的。流量控制配額檢查(即檢查生產者是否有足夠配額)僅在客戶端完成。代理程式有可能會過度分配配額,例如上面概述的多生產者案例。不當行為的用戶端也有可能忽略代理程式發出的流量控制配額,並在沒有足夠配額的情況下繼續傳送。

2.1.2. 封鎖 AMQP 生產者

Apache ActiveMQ Artemis 隨附 2 個支援流量控制的現成協定。Artemis CORE 協定和 AMQP。這兩種協定以稍微不同的方式實作流量控制,因此位址完整 BLOCK 原則對於分別使用每種協定的用戶端的行為略有不同。

如同本章前面所述,CORE協定使用生產者視窗大小流量控制系統。在該系統中,會為生產者分配額度(代表位元組)。如果生產者想要傳送訊息,它應該等待直到有足夠的位元組額度可用於傳送。AMQP流量控制額度並不代表位元組,而是代表允許生產者傳送的訊息數量(無論訊息大小)。

AMQP的BLOCK機制與上述生產者視窗大小機制的工作方式大致相同。Artemis會一次向客戶端發放100個額度,並在客戶端的額度達到30時刷新。一旦位址已滿,代理伺服器將停止發放額度。然而,由於AMQP額度代表的是完整訊息而不是位元組,在某些情況下,如果代理伺服器持續接受訊息直到客戶端的額度用盡,AMQP客戶端可能會顯著超過位址的上限。因此,位址設定上還有一個額外的參數,用於指定位址大小的位元組上限。一旦達到此上限,Artemis將開始拒絕AMQP訊息。此限制是max-size-bytes-reject-threshold,預設設定為-1(或無限制)。此額外參數允許某種軟性限制和硬性限制。在正常情況下,代理伺服器將利用max-size-bytes參數使用流量控制來對客戶端施加回壓,但一旦達到位址大小,將通過拒絕訊息來保護代理伺服器。

2.2. 速率限制流量控制

Apache ActiveMQ Artemis也允許限制生產者發送訊息的速率,單位為每秒訊息數。通過指定這樣的速率,Apache ActiveMQ Artemis將確保生產者永遠不會以高於指定速率的速率產生訊息。這由producerMaxRate URL參數控制。

producerMaxRate必須是一個正整數才能啟用此功能,並且是以每秒訊息數為單位指定的最大期望訊息產生速率。將其設定為-1會停用速率限制流量控制。預設值為-1

請參閱範例章節以獲取限制生產者速率的工作範例。