Apache ActiveMQ Artemis 透明地支援在伺服器以有限記憶體運作時,包含數百萬條訊息的大型佇列。

在這種情況下,不可能一次將所有佇列都儲存在記憶體中,因此 Apache ActiveMQ Artemis 會在需要時透明地將訊息分頁進出記憶體,從而允許具有低記憶體佔用的大型佇列。

當位址中所有記憶體內訊息的大小超過設定的最大大小時,Apache ActiveMQ Artemis 將開始將訊息分頁到磁碟。

Artemis 的預設設定具有啟用分頁的目的地。

1. 分頁檔案

訊息會依位址儲存在檔案系統上。每個位址都有一個個別的資料夾,其中訊息儲存在多個檔案(分頁檔案)中。每個檔案將包含訊息直到設定的最大大小 (page-size-bytes)。系統會根據需要瀏覽檔案,並在所有訊息都確認到該點後,立即移除分頁檔案。

瀏覽器將讀取分頁游標系統。

帶有選取器的消費者也會瀏覽分頁檔案,並會忽略不符合條件的訊息。

當您有一個佇列,且消費者使用非常嚴格的選取器篩選佇列時,您可能會遇到一種情況,在您從佇列中取用訊息之前,您將無法從分頁中讀取更多資料。

範例:在一個消費者中,您將選取器設定為 'color="red"',但您只有在藍色之後的 100 萬條紅色訊息,在您取用藍色訊息之前,您將無法取用紅色訊息。

這與瀏覽不同,因為我們將「瀏覽」整個佇列以尋找訊息,並且在為佇列饋送訊息時「取消分頁」訊息。

1.1. 設定

您可以在 broker.xml 中設定分頁資料夾的位置。

  • paging-directory 分頁檔案的儲存位置。Apache ActiveMQ Artemis 將在此設定位置下為每個正在分頁的位址建立一個資料夾。預設值為 data/paging

2. 分頁模式

一旦傳遞到位址的訊息超過設定的大小,該位址就會進入分頁模式。如果 max-size-bytes == 0 或 max-size-messages == 0,則位址將始終使用分頁來路由訊息。

分頁是依位址個別完成的。如果您為位址設定 max-size-bytes 或 max-messages,這表示每個符合條件的位址都將具有您指定的最大大小。這並不表示所有符合條件的位址的總體大小限制為 max-size-bytes。請使用 global-max-sizeglobal-max-messages 來達到此目的!

2.1. 設定

設定是在 broker.xml 中的位址設定中完成的。

<address-settings>
   <address-setting match="jms.someaddress">
      <max-size-bytes>104857600</max-size-bytes>
      <max-size-messages>1000</max-size-messages>
      <page-size-bytes>10485760</page-size-bytes>
      <address-full-policy>PAGE</address-full-policy>
      <page-limit-bytes>10G</page-limit-bytes>
      <page-limit-messages>1000000</page-limit-messages>
      <page-full-policy>FAIL</page-full-policy>
   </address-setting>
</address-settings>
管理位址設定無法變更或覆寫,即不允許管理訊息分頁/封鎖/失敗,並且被視為內部代理程式管理機制。管理位址的記憶體佔用量在評估是否達到 global-max-size 時不予考慮,並且不會導致其他非管理位址觸發設定的 address-full-policy

這是位址設定上可用的參數清單。

屬性名稱 描述 預設值

max-size-bytes

位址在進入分頁模式之前可以擁有的最大記憶體量。

-1 (已停用)

max-size-messages

位址在進入分頁模式之前可以擁有的最大訊息數。

-1 (已停用)

page-size-bytes

分頁系統上使用的每個分頁檔案的大小

10MB

address-full-policy

必須將此設定為 PAGE 才能啟用分頁。如果值為 PAGE,則進一步的訊息將分頁到磁碟。如果值為 DROP,則將會靜默地丟棄進一步的訊息。如果值為 FAIL,則將丟棄訊息,並且用戶端訊息生產者將收到例外。如果值為 BLOCK,則當用戶端訊息生產者嘗試傳送進一步的訊息時,將會被封鎖。

PAGE

max-read-page-messages

每個佇列代理程式可以讀取到記憶體中的最大分頁訊息數。預設值為 -1,表示不套用任何限制。

-1 (已停用)

max-read-page-bytes

每個佇列可以用於將分頁訊息讀取到記憶體中的最大記憶體量(以位元組為單位)。在套用此限制時,代理程式會考量目前正在傳遞的訊息和準備傳遞給消費者的訊息。預設值為 2 * page-size(通常為 20 MB)。如果消費者確認訊息的速度較慢,您可以增加預設值,以確保記憶體不會被等待確認的訊息消耗,這可能會使代理程式缺乏訊息。

2 * page-size-bytes

prefetch-page-messages

代理程式可以從磁碟讀取到記憶體中每個佇列的分頁訊息數。預設值取自 max-read-page-messages,通常為 -1,表示不套用任何限制。

max-read-page-messages

prefetch-page-bytes

代理程式可以從磁碟讀取到記憶體中每個佇列的分頁訊息數。預設值取自 max-read-page-messages,通常為 -1,表示不套用任何限制。

如果未定義,則為 max-read-page-bytes

page-limit-bytes

進入分頁模式後,系統將允許多少資料進入。請注意,這將在內部轉換為頁數。

page-limit-messages

進入分頁模式後,系統將允許多少訊息進入分頁。

page-full-policy

有效結果為 DROP 或 FAIL。這表示如果系統在分頁後達到 page-limit-bytespage-limit-messages 時,該怎麼做

當使用 JDBC 儲存體時,所使用的有效 page-size-bytes 會限制為在 JDBC 儲存體區段中設定的 jdbc-max-page-size-bytes。

2.2. max-size-bytes 和 max-size-messages 同時使用

可以同時定義 max-size-messages (作為最大訊息數) 和 max-messages-size (作為位址使用的估計記憶體上限)。設定的原則將根據第一個達到其標記的值開始。

2.2.1. 從分頁讀取最大值

max-read-page-messagesmax-read-page-bytesprefetch-page-messagesprefetch-page-bytes 用於控制從分頁檔案讀取到佇列。只要滿足所有這些限制,代理程式就會新增訊息。

如果所有這些值都設定為 -1,則只要消費者需要更多訊息,代理程式就會繼續讀取訊息。但是,這會使代理程式無法防範分配大量交易或未啟用流量控制的消費者。

3. 全域最大大小

除了位址上的 max-size-bytes 之外,您還可以在主要設定上設定 global-max-size。如果在分頁時將 max-size-bytes = -1,則仍然可以使用 global-max-size

4. 全域最大訊息數

您還可以在主要設定上指定 global-max-messages,指定系統在進入設定的完整原則模式之前會接受多少訊息。

當您的訊息超過設定的 global-max-size 時,任何新的生產訊息都會使該目的地執行其分頁原則。

global-max-size 計算為 Java 虛擬機器可用最大記憶體的一半,除非在 broker.xml 設定中指定。

預設情況下,global-max-messages = -1,表示已停用。

5. 丟棄訊息

除了在達到最大大小時分頁訊息之外,還可以將位址設定為在位址已滿時僅丟棄訊息。

若要執行此操作,只需在位址設定中將 address-full-policy 設定為 DROP

6. 丟棄訊息並向生產者拋出例外

除了在達到最大大小時分頁訊息之外,還可以將位址設定為在位址已滿時丟棄訊息,並在用戶端拋出例外。

若要執行此操作,只需在位址設定中將 address-full-policy 設定為 FAIL

7. 封鎖生產者

除了在達到最大大小時分頁訊息之外,還可以將位址設定為在位址已滿時封鎖生產者傳送進一步的訊息,從而防止伺服器上的記憶體耗盡。

當伺服器上的記憶體釋放時,生產者將會自動解除封鎖,並且能夠繼續傳送。

若要執行此操作,只需在位址設定中將 address-full-policy 設定為 BLOCK

在預設設定中,所有位址都設定為在位址中有 10 MiB 的資料後封鎖生產者。

8. 具有多個多播佇列的位址的注意事項

當訊息路由到具有多個繫結到它的多播佇列的位址時,例如主題中的 JMS 訂閱,記憶體中只有 1 個訊息副本。每個佇列只會處理對此的參考。因此,只有在所有參考訊息的佇列都傳遞訊息之後,才會釋放記憶體。

如果您有一個單一的延遲訂閱,則整個位址將會受到 IO 效能的影響,因為所有佇列都會有訊息通過分頁系統上的額外儲存體傳送。

例如

  • 一個位址有 10 個多點傳播佇列

  • 其中一個佇列無法傳遞其訊息(可能是因為消費者速度緩慢)。

  • 訊息不斷地傳送到該位址,並開始分頁。

  • 即使已傳送訊息,其他 9 個佇列仍為空。

在此範例中,其他 9 個佇列將會從分頁系統取用訊息。如果這是不希望發生的狀態,可能會導致效能問題。

9. 監控磁碟

可以設定 Broker 對磁碟執行掃描,以判斷磁碟是否超出設定的限制。由於磁碟是資料完整性的關鍵基礎架構,因此如果磁碟空間用完,Broker 會自動關閉。設定限制可讓 Broker 對傳送訊息至 Broker 的用戶端強制執行流量控制,以便磁碟永遠不會完全填滿。

如果用來傳送訊息的協定不支援流量控制(例如 STOMP),則會擲回例外狀況,並且會捨棄用戶端的連線,使其無法再傳送訊息並佔用磁碟空間。

9.1. 最大磁碟使用量

可以透過 max-disk-usage 設定使用的最大磁碟空間限制。這是已使用的磁碟百分比。例如,如果磁碟容量為 500GiB,且 max-disk-usage50,則當使用 250GiB 的磁碟空間時,Broker 會開始封鎖生產者。

9.2. 最小可用磁碟空間

可以透過 min-disk-free 設定最小可用磁碟空間限制。這是一個特定數量,而不是像 max-disk-usage 一樣的百分比。例如,如果磁碟容量為 500GiB,且 min-disk-free100GiB,則當使用 400GiB 的磁碟空間時,Broker 會開始封鎖生產者。

如果同時設定 max-disk-usagemin-disk-free,則 min-disk-free 將優先。

10. 分頁同步逾時

會定期同步頁面,同步週期會透過奈秒為單位的 page-sync-timeout 進行設定。使用 NIO 日誌時,預設值與 journal-buffer-timeout 的值相同。使用 ASYNCIO 時,預設值應為 3333333

11. 來自已分頁訊息的記憶體使用量。

系統應至少將一個已分頁的檔案保留在記憶體中,以便提前快取讀取訊息。此外,每個作用中的訂閱都可以在記憶體中保留一個已分頁的檔案。因此,如果您的系統有太多佇列,建議盡量縮小頁面大小。

12. 分頁限制和分頁滿載原則

自版本 2.28.0 起,可以設定分頁資料量的限制。這是為了避免單一目的地在其消費者消失時使用整個磁碟。

您可以設定 page-limit-bytespage-limit-messages 以及位址設定中的 page-full-policy,以限制分頁中記錄的資料量。

如果您將 page-full-policy 設定為 DROP,則會直接捨棄訊息,而用戶端不會收到任何例外狀況;如果您將其設定為 FAIL,則生產者會收到關於錯誤狀況的 JMS 例外狀況。

page-limit-bytes 用於識別內部最大頁面檔案數(即 page-limit-bytes / page-size-bytes),然後與目前頁面檔案數進行比較。如果已設定,則 page-limit-bytes 必須等於或大於 page-size-bytes,否則會立即遭到封鎖。如果從 page-limit-bytes 判斷出的限制值(一旦轉換為頁面數)小於儲存區中的目前頁面檔案數,則會根據 page-full-policy 封鎖分頁,直到目前的頁面檔案數降至小於或等於計算的檔案限制值。一旦頁面檔案數大於 page-limit-bytes (page-limit-bytes / page-size-bytes) 所判斷的值,就會再次遭到封鎖。

13. 範例

請參閱分頁範例,其中說明如何搭配使用分頁與 Apache ActiveMQ Artemis。