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-size 或 global-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 。 |
這是位址設定上可用的參數清單。
屬性名稱 | 描述 | 預設值 |
---|---|---|
|
位址在進入分頁模式之前可以擁有的最大記憶體量。 |
-1 (已停用) |
|
位址在進入分頁模式之前可以擁有的最大訊息數。 |
-1 (已停用) |
|
分頁系統上使用的每個分頁檔案的大小 |
10MB |
|
必須將此設定為 |
|
|
每個佇列代理程式可以讀取到記憶體中的最大分頁訊息數。預設值為 -1,表示不套用任何限制。 |
-1 (已停用) |
|
每個佇列可以用於將分頁訊息讀取到記憶體中的最大記憶體量(以位元組為單位)。在套用此限制時,代理程式會考量目前正在傳遞的訊息和準備傳遞給消費者的訊息。預設值為 2 * page-size(通常為 20 MB)。如果消費者確認訊息的速度較慢,您可以增加預設值,以確保記憶體不會被等待確認的訊息消耗,這可能會使代理程式缺乏訊息。 |
2 * page-size-bytes |
prefetch-page-messages |
代理程式可以從磁碟讀取到記憶體中每個佇列的分頁訊息數。預設值取自 max-read-page-messages,通常為 -1,表示不套用任何限制。 |
|
prefetch-page-bytes |
代理程式可以從磁碟讀取到記憶體中每個佇列的分頁訊息數。預設值取自 max-read-page-messages,通常為 -1,表示不套用任何限制。 |
如果未定義,則為 |
|
進入分頁模式後,系統將允許多少資料進入。請注意,這將在內部轉換為頁數。 |
|
|
進入分頁模式後,系統將允許多少訊息進入分頁。 |
|
|
有效結果為 DROP 或 FAIL。這表示如果系統在分頁後達到 |
當使用 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-messages
、max-read-page-bytes
、prefetch-page-messages
和 prefetch-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-usage
為 50
,則當使用 250GiB 的磁碟空間時,Broker 會開始封鎖生產者。
9.2. 最小可用磁碟空間
可以透過 min-disk-free
設定最小可用磁碟空間限制。這是一個特定數量,而不是像 max-disk-usage
一樣的百分比。例如,如果磁碟容量為 500GiB,且 min-disk-free
為 100GiB
,則當使用 400GiB 的磁碟空間時,Broker 會開始封鎖生產者。
如果同時設定 max-disk-usage 和 min-disk-free ,則 min-disk-free 將優先。 |
10. 分頁同步逾時
會定期同步頁面,同步週期會透過奈秒為單位的 page-sync-timeout
進行設定。使用 NIO 日誌時,預設值與 journal-buffer-timeout
的值相同。使用 ASYNCIO 時,預設值應為 3333333
。
11. 來自已分頁訊息的記憶體使用量。
系統應至少將一個已分頁的檔案保留在記憶體中,以便提前快取讀取訊息。此外,每個作用中的訂閱都可以在記憶體中保留一個已分頁的檔案。因此,如果您的系統有太多佇列,建議盡量縮小頁面大小。
12. 分頁限制和分頁滿載原則
自版本 2.28.0
起,可以設定分頁資料量的限制。這是為了避免單一目的地在其消費者消失時使用整個磁碟。
您可以設定 page-limit-bytes
或 page-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 ) 所判斷的值,就會再次遭到封鎖。 |