Apache ActiveMQ Artemis 包含強大的自動重複訊息偵測功能,無需您在應用程式層級編寫繁瑣的重複偵測邏輯即可過濾掉重複訊息。本章將說明重複偵測是什麼、Apache ActiveMQ Artemis 如何使用它,以及如何在何處設定它。
當從用戶端傳送訊息到伺服器,或實際上從伺服器傳送到另一個伺服器時,如果目標伺服器或連線在傳送訊息後,但在傳送者收到傳送(或提交)已成功處理的回應之前發生故障,則傳送者無法確定訊息是否已成功傳送到位址。
如果目標伺服器或連線在收到並處理傳送後,但在回覆傳回之前發生故障,則訊息將已成功傳送到位址,但如果目標伺服器或連線在收到傳送並完成處理之前發生故障,則它將無法成功傳送到位址。從傳送者的角度來看,無法區分這兩種情況。
當伺服器恢復時,這會讓用戶端陷入困境。它知道目標伺服器發生故障,但它不知道最後一條訊息是否已成功送達目的地。如果它決定重新傳送最後一條訊息,則可能會導致重複訊息被傳送到位址。如果每條訊息都是訂單或交易,則可能會導致訂單被履行兩次或交易被重複預訂。這顯然不是一個理想的情況。
在交易中傳送訊息也無濟於事。如果在處理交易提交時伺服器或連線發生故障,也無法確定交易是否已成功提交!
為了解決這些問題,Apache ActiveMQ Artemis 為傳送到位址的訊息提供自動重複訊息偵測功能。
1. 使用重複偵測進行訊息傳送
為傳送的訊息啟用重複訊息偵測非常簡單:您只需將訊息上的特殊屬性設定為唯一值即可。您可以隨意建立值,只要它是唯一的即可。當目標伺服器收到訊息時,它會檢查是否已設定該屬性,如果已設定,則會在其記憶體快取中檢查是否已收到具有該標頭值的訊息。如果之前已收到具有相同值的訊息,則它將忽略該訊息。
使用重複偵測在節點之間移動訊息可以提供與使用 XA 交易從來源消耗訊息並將其傳送到目標相同的 * 一次且僅一次 * 傳遞保證,但開銷更少,並且比使用 XA 更易於設定。 |
如果您在交易中傳送訊息,則不必為您在該交易中傳送的 * 每條 * 訊息設定屬性,您只需要在交易中設定一次即可。如果伺服器偵測到交易中任何訊息的重複訊息,則它將忽略整個交易。
您設定的屬性名稱由 org.apache.activemq.artemis.api.core.Message.HDR_DUPLICATE_DETECTION_ID
的值給定,該值為 _AMQ_DUPL_ID
。
如果您使用核心 API,則屬性的值可以是 byte[]
或 SimpleString
類型。如果您使用 JMS,則它必須是 String
,並且其值應為唯一值。產生唯一 ID 的一個簡單方法是產生 UUID。
以下是使用核心 API 設定屬性的範例
...
ClientMessage message = session.createMessage(true);
SimpleString myUniqueID = "This is my unique id"; // Could use a UUID for this
message.setStringProperty(HDR_DUPLICATE_DETECTION_ID, myUniqueID);
以下是使用 JMS API 的範例
...
Message jmsMessage = session.createMessage();
String myUniqueID = "This is my unique id"; // Could use a UUID for this
message.setStringProperty(HDR_DUPLICATE_DETECTION_ID.toString(), myUniqueID);
...
2. 設定重複 ID 快取
伺服器會維護傳送到每個位址的 org.apache.activemq.artemis.core.message.impl.HDR_DUPLICATE_DETECTION_ID
屬性接收值的快取。每個位址都有其各自不同的快取。
快取是一個循環固定大小的快取。如果快取的最大大小為 n
個元素,則儲存的第 n + 1
個 ID 將覆寫快取中的第 0
個元素。
快取的最大大小由 broker.xml
中的參數 id-cache-size
設定,預設值為 20000
個元素。
若要實作特定於位址的 id-cache-size
,您可以在 broker.xml
中新增到相應的 address-settings 區段。為特定位址指定所需的 id-cache-size
值。當訊息傳送到具有特定 id-cache-size
設定的位址時,它將優先於全域 id-cache-size
值,從而實現更大的彈性和重複 ID 快取的最佳化。
快取也可以設定為是否儲存到磁碟。這由 broker.xml
中的參數 persist-id-cache
設定。如果此值設定為 true
,則每個 ID 在接收時都會儲存到永久儲存空間。此參數的預設值為 true
。
在選擇重複 ID 快取的大小時,請務必將其設定為足夠大的大小,以便在您重新傳送訊息時,所有先前傳送的訊息都已在快取中,而不會被覆寫。 |
3. 重複偵測與橋接器
可以將核心橋接器設定為在將訊息轉寄到其目標之前自動新增唯一的重複 ID 值(如果訊息中還沒有)。這可確保如果目標伺服器當機或連線中斷,且橋接器重新傳送訊息,則如果目標伺服器已收到訊息,則會忽略該訊息。
若要設定核心橋接器以新增重複 ID 標頭,只需在 broker.xml
中設定橋接器時,將 use-duplicate-detection
設定為 true
。
此參數的預設值為 true
。
如需有關核心橋接器及其設定方式的詳細資訊,請參閱核心橋接器。
4. 重複偵測與叢集連線
叢集連線在內部使用核心橋接器,以便在叢集的節點之間可靠地移動訊息。因此,也可以將它們設定為使用其內部橋接器為他們移動的每條訊息插入重複 ID 標頭。
若要設定叢集連線以新增重複 ID 標頭,只需在 broker.xml
中設定叢集連線時,將 use-duplicate-detection
設定為 true
。
此參數的預設值為 true
。
如需有關叢集連線及其設定方式的詳細資訊,請參閱叢集。