跳至主要內容
版本:5.0

消費者負載平衡

當消費者群組中的消費者從 Apache RocketMQ 主題擷取訊息時,負載平衡政策用於決定如何將訊息分配給消費者。負載平衡政策可改善服務並行性和應用程式可擴充性。本主題說明 Apache RocketMQ 為消費者提供的負載平衡政策。

背景資訊

熟悉 Apache RocketMQ 提供的負載平衡政策,可協助您在遇到下列情況時採取適當措施

  • 災難復原:您可以決定在本地節點發生故障時如何重試和切換訊息。

  • 訊息排序:您可以更了解 Apache RocketMQ 如何確保嚴格的先進先出訊息排序。

  • 水平分區:您可以根據訊息配置方式,規劃流量遷移和水平擴充作業。

廣播消費和叢集消費

Apache RocketMQ 允許多個消費者群組訂閱同一則訊息,每個消費者群組初始化多個消費者。消費者群組和消費者可以設定在下列情境中消費訊息:消費模式

  • 跨消費者群組的廣播消費:此情境說明於前述圖形的左側。每個消費者群組初始化自己的消費者,由該消費者消費所有訊息。訊息從主題傳送給多個訂閱者,形成一對多的關係。

    此模式通常用於閘道推播和組態推播等情境。

  • 消費者群組內的叢集消費:此情境說明於前述圖形的右側。每個消費者群組初始化多個消費者,訊息會傳送給群組中的所有消費者。當您要在群組內實作水平流量分區和負載平衡時,這會很有用。

    此模式適合微服務解耦。

消費者負載平衡政策簡介

在使用廣播消費的情境中,不需要負載平衡,因為每個消費者群組只包含一個消費者。

然而,在使用叢集消費的情境中,每個消費者群組包含多個消費者。負載平衡政策有助於決定如何配置訊息。

根據消費者類型,負載平衡政策可分為下列兩種

基於訊息的負載平衡

使用範圍

基於訊息的負載平衡是推播消費者和簡易消費者的唯一且預設政策。

工作機制

基於訊息的負載平衡將主題中的訊息平均分配給消費者群組中的多個消費者。 基於訊息的負載平衡

如上圖所示,消費者群組 A 包含三個消費者:A1、A2 和 A3。這三個消費者會使用主題中 Queue1 的訊息。

注意

基於訊息的負載平衡可確保佇列中的訊息可由多個消費者同時處理。然而,訊息會隨機傳送給消費者,這表示您無法指定如何將訊息分配給消費者。

基於訊息的負載平衡是根據主題中單一訊息的確認語意。消費者收到訊息後,仲介會鎖定訊息以確保其他消費者在訊息被使用或逾時之前無法看到它。這可防止不同消費者多次使用同一佇列的訊息。

已排序訊息的負載政策

在已排序訊息中,訊息順序是指訊息群組中多個訊息的順序。這些訊息必須按照儲存在仲介上的順序處理。因此,基於訊息的負載平衡需要確保訊息群組中的訊息按照儲存在伺服器上的順序使用。當不同的消費者處理同一群組中的訊息時,系統會嚴格按照訊息順序鎖定訊息,以確保訊息依序使用。 已排序訊息的負載政策

在上述圖中,Queue1 的消息組 G1 中有四條已排序的消息,儲存順序分別為 M1 到 M4。在消費過程中,當消息 M1 和 M2 被消費者 A1 處理時,如果 M1 和 M2 的消費狀態尚未提交,則消費者 A2 無法並行消費消息 M3 和 M4。只有在上一個消息的消費狀態提交後,消費者才能消費消息。

特點

與基於佇列的負載均衡相比,基於消息的負載均衡具有以下特點

  • 更均衡的消費分配。在傳統的基於佇列的負載均衡中,佇列數和消費者數可能無法得到很好的平衡,導致有的消費者閒置,而有的消費者負擔過重。相比之下,基於消息的負載均衡確保了消費者之間的負載均勻,而無需管理佇列數和消費者數。
  • 對網路能力差異的容忍度更高。在線上生產環境中,由於實際網路狀況或網路硬體規格不一致,消費者的處理能力可能不同。如果按佇列分配消息,可能會出現有的消費者積壓了大量消息,而有的消費者卻閒置的情況。相比之下,基於消息的負載均衡按需分配消息,實現了消費者之間更均衡的負載分佈。
  • 佇列分配的運維更簡便。在使用傳統的基於佇列的負載均衡時,必須確保佇列數大於或等於消費者數,以保證沒有消費者閒置。而基於消息的負載均衡不存在這個問題。

適用場景

由於佇列中的消息是離散地分配給消費者的,因此基於消息的負載均衡適用於大多數線上事件處理場景。在這些場景中,消費者只需要基本的處理能力,而不需要對消息進行批次聚合。對於需要對消息進行聚合和批次處理的場景,例如流處理和聚合計算,基於佇列的負載均衡是更好的選擇。範例

消費者無需為基於消息的負載均衡進行額外的配置。預設情況下,此策略對推送消費者和簡單消費者啟用。

        SimpleConsumer simpleConsumer = null;
// Consumption example 1: When push consumers consume normal messages, they need only to process messages on a message listener and do not need to consider load balancing.
MessageListener messageListener = new MessageListener() {
@Override
public ConsumeResult consume(MessageView messageView) {
System.out.println(messageView);
// Return the status based on the consumption result.
return ConsumeResult.SUCCESS;
}
};
// Consumption example 2: When simple consumers consume normal messages, they obtain and submit messages. The consumers obtain messages based on the subscribed topic and do not need to consider load balancing.
List<MessageView> messageViewList = null;
try {
messageViewList = simpleConsumer.receive(10, Duration.ofSeconds(30));
messageViewList.forEach(messageView -> {
System.out.println(messageView);
// After consumption is complete, consumers must invoke ACK to submit the consumption result.
try {
simpleConsumer.ack(messageView);
} catch (ClientException e) {
e.printStackTrace();
}
});
} catch (ClientException e) {
// If the pull fails due to system traffic throttling or other reasons, consumers must re-initiate the request to obtain the message.
e.printStackTrace();
}

基於佇列的負載均衡

使用範圍

對於包括 PullConsumer、DefaultPushConsumer、DefaultPullConsumer 和 DefaultLitePullConsumer 在內的 4.x 和 3.x 版本的代理程式消費者,只能使用基於佇列的負載均衡。

工作機制

在基於佇列的負載均衡策略中,同一個消費者組中的消費者消費分配給自己的佇列中的消息。每個佇列由一個消費者消費。 队列级负载均衡原理

如上圖所示,主題中的三個佇列(Queue1、Queue2 和 Queue3)被分配給消費者組中的兩個消費者。由於每個佇列只能分配給一個消費者,因此消費者 A2 被分配了兩個佇列。如果佇列數小於消費者數,則會有消費者沒有分配到佇列。

基於佇列的負載均衡根據佇列數、消費者數等運營資料分配消息。每個佇列都綁定一個具體的消費者,然後每個消費者按照獲取消息 > 提交位移 > 持久化位移的消費語義處理消息。消費者獲取消息時,不會將消費狀態回傳給佇列。因此,為了避免多個消費者重複消費消息,每個佇列只能由一個消費者消費。

注意

基於佇列的負載平衡保證一個佇列只會被一個消費者處理。然而,此政策的實作取決於消費者與代理伺服器之間的資訊協商機制。

Apache RocketMQ 無法保證佇列中的訊息只會被一個消費者處理。因此,當消費者數目和佇列數目改變時,可能會發生佇列分配暫時不一致的情況,導致少數訊息被處理超過一次。

特點

與基於訊息的負載平衡相比,基於佇列的負載平衡的粒度較大且較不靈活。然而,基於佇列的負載平衡非常適合串流處理場景。它確保佇列中的訊息只會被一個消費者處理。因此,基於佇列的負載平衡更適合您想要處理彙總訊息或批次訊息的場景。

適用場景

基於佇列的負載平衡適用於您想要處理彙總訊息或批次訊息的場景。這些是串流運算和資料彙總應用程式中的常見場景。

範例

消費者不需要針對基於佇列的負載平衡執行額外的設定。預設情況下,此政策已針對代理伺服器版本 4.x 和 3.x 的拉取消費者啟用。

如需有關範例程式碼的更多資訊,請參閱 Apache RocketMQ 的程式碼庫

版本相容性

基於訊息的負載平衡政策可從 Apache RocketMQ 的代理伺服器版本 5.0 開始使用。對於代理伺服器版本 4.x 和 3.x,僅提供基於佇列的負載平衡政策。

基於訊息和基於佇列的負載平衡政策都可用於 Apache RocketMQ 的代理伺服器版本 5.x。哪個政策有效取決於客戶端版本和消費者類型。

使用注意事項

為使用邏輯實作訊息冪等性。

基於訊息和基於佇列的負載平衡政策都會在新增消費者、移除消費者和代理伺服器擴充等場景中觸發暫時重新平衡。這可能會導致暫時負載不一致,並導致少數訊息被使用超過一次。因此,有必要執行重複資料刪除以確保訊息使用的冪等性。