コンシューマーグループのコンシューマーがApsaraMQ for RocketMQトピックからメッセージをプルする場合、負荷分散ポリシーを使用して、メッセージがコンシューマーにどのように割り当てられるかを決定します。 負荷分散ポリシーは、サービスの同時実行性とアプリケーションのスケーラビリティを向上させます。 このトピックでは、ApsaraMQ for RocketMQがコンシューマーに提供する負荷分散ポリシーについて説明します。
背景情報
ApsaraMQ for RocketMQが提供する負荷分散ポリシーをよく理解することで、次のシナリオに直面したときに実行する適切な対策を決定することができます。
ディザスタリカバリ: ローカルノードに障害が発生した場合のメッセージの再試行および切り替え方法を確認できます。
メッセージの順序付け: ApsaraMQ for RocketMQが、先入れ先出しメッセージの厳密な順序付けを保証する方法をよりよく理解できます。
水平パーティショニング: メッセージの割り当て方法に基づいて、トラフィックの移行と水平スケーリング操作を計画できます。
ブロードキャスト消費とクラスター消費
ApsaraMQ for RocketMQでは、複数のコンシューマグループが同じメッセージをサブスクライブし、各コンシューマグループが複数のコンシューマを初期化できます。 コンシューマーグループとコンシューマーは、次のシナリオでメッセージを消費するように構成できます。
消費者グループ間のブロードキャスト消費: このシナリオは、前の図の左側に示されています。 各コンシューマグループは、すべてのメッセージを消費する独自のコンシューマを初期化します。 メッセージは、1対多の関係でトピックから複数の購読者に配信されます。
このモードは通常、ゲートウェイプッシュや構成プッシュなどのシナリオで使用されます。
コンシューマーグループ内のクラスター消費: このシナリオは、前の図の右側に示されています。 各コンシューマグループは複数のコンシューマを初期化し、メッセージはグループ内のすべてのコンシューマに送信されます。 これは、グループ内で水平方向のトラフィック分割と負荷分散を実装する場合に便利です。
このモードは、マイクロサービスのデカップリングに適しています。
コンシューマー向けの負荷分散ポリシーの概要
ブロードキャスト消費を使用するシナリオでは、各コンシューマグループに1つのコンシューマしか含まないため、負荷分散は必要ありません。
ただし、クラスター消費を使用するシナリオでは、各コンシューマグループに複数のコンシューマが含まれます。 負荷分散ポリシーは、メッセージの割り当て方法を決定するのに役立ちます。
コンシューマータイプに基づいて、負荷分散ポリシーは次の2つのタイプに分類できます。
メッセージベースの負荷分散: プッシュコンシューマとシンプルコンシューマのデフォルトポリシー。
キューベースの負荷分散: プルコンシューマーのデフォルトポリシー。
メッセージベースの負荷分散
使用範囲
メッセージベースのロードバランシングは、プッシュコンシューマとシンプルコンシューマの唯一のデフォルトポリシーです。
働くメカニズム
メッセージベースの負荷分散は、トピック内のメッセージをコンシューマグループ内の複数のコンシューマに均等に割り当てます。
前の図に示すように、消費者グループAは3つの消費者A1、A2、およびA3で構成されています。 これら3つのコンシューマーは、トピック内のキュー1のメッセージを消費します。
メッセージベースの負荷分散により、キュー内のメッセージを複数のコンシューマが同時に処理できるようになります。 ただし、メッセージはコンシューマーにランダムに送信されるため、コンシューマーへのメッセージの割り当て方法を指定することはできません。
メッセージベースの負荷分散は、トピック内の単一のメッセージの肯定応答セマンティクスに基づいています。 消費者がメッセージを受信した後、ブローカーはメッセージをロックして、消費されるかタイムアウトするまで他の消費者には見えないようにします。 これにより、同じキューのメッセージが異なるコンシューマによって複数回消費されるのを防ぎます。
順序付きメッセージのロードポリシー
順序付けられたメッセージでは、メッセージの順序は、メッセージグループ内の複数のメッセージのシーケンスを指します。 これらのメッセージは、ブローカーに保存されているのとまったく同じ順序で処理する必要があります。 したがって、メッセージベースの負荷分散では、メッセージグループ内のメッセージがサーバーに保存されている順序と同じ順序で消費されるようにする必要があります。 異なるコンシューマーが同じグループ内のメッセージを処理する場合、システムはメッセージの順序に従ってメッセージをロックし、メッセージが順番に消費されるようにします。
前の図では、キュー1のメッセージグループG1に4つの順序付きメッセージがあります。 それらの保存順序はM1〜M4によって表される。 消費中、メッセージM1およびM2が消費者A1によって処理されるとき、消費者A2は、M1およびM2の消費ステータスが送信されない場合、メッセージM3およびM4を並行して消費することができない。 コンシューマは、先行するメッセージの消費ステータスが送信された場合にのみメッセージを消費できます。
特徴
キューベースのロードバランシングと比較して、メッセージベースのロードバランシングには次の機能があります。
よりバランスの取れた消費配分
従来のキューベースのロードバランシングでは、キューの数とコンシューマの数とが適切にバランスされないことがある。 この結果、一部の消費者はアイドル状態になり、一部の消費者は過負荷になる。 比較すると、メッセージベースのロードバランシングは、キューとコンシューマーの数を管理する必要なしに、コンシューマー間の均等なロードバランシングを保証します。
ネットワーキング能力の違いをより寛容にする
オンライン生産環境では、消費者の処理能力は、実際のネットワーク条件または一貫性のないネットワーキングハードウェア仕様のために異なる場合があります。 メッセージがキューに基づいて割り当てられる場合、一部の消費者がメッセージを蓄積し、一部の消費者がアイドル状態にある場合があります。 対照的に、メッセージベースの負荷分散は、需要に応じてメッセージを割り当てて、消費者間でよりバランスの取れた負荷分散を実現します。
キュー割り当てのためのより簡単なO&M
従来のキューベースのロードバランシングが使用されるシナリオでは、キューの数がコンシューマーの数以上であることを確認して、コンシューマーがアイドル状態にならないようにする必要があります。 この問題は、メッセージベースの負荷分散では発生しません。
シナリオ
キュー内のメッセージはコンシューマに個別に割り当てられるため、メッセージベースの負荷分散は、ほとんどのオンラインイベント処理シナリオに適しています。 これらのシナリオでは、コンシューマはメッセージのバッチ集約ではなく、基本的な処理機能のみを必要とします。 メッセージの集約とバッチ処理が必要なストリーム処理や集約コンピューティングなどのシナリオでは、キューベースの負荷分散をお勧めします。
例:
コンシューマは、メッセージベースの負荷分散のために追加の設定を実行する必要はありません。 デフォルトでは、このポリシーはプッシュコンシューマとシンプルコンシューマに対して有効になっています。
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();
}
キューベースの負荷分散
使用範囲
プルコンシューマー、デフォルトプッシュコンシューマー、デフォルトプルコンシューマー、ライトプルコンシューマーを含むブローカーバージョン4.xおよび3.xのコンシューマーの場合、キューベースの負荷分散のみを使用できます。
働くメカニズム
キューベースの負荷分散ポリシーでは、同じコンシューマーグループ内のコンシューマーは、自分に割り当てられたキュー内のメッセージを消費します。 各キューは1つのコンシューマによって消費されます。
前の図に示すように、トピックの3つのキュー (Queue1、Queue2、およびQueue3) は、コンシューマグループの2つのコンシューマに割り当てられます。 各キューは1つのコンシューマにしか割り当てられないので、コンシューマA2には2つのキューが割り当てられる。 キューの数がコンシューマの数よりも少ない場合、一部のコンシューマにはキューが割り当てられていません。
キューベースのロードバランシングは、キューの数やコンシューマーの数などのオペレーティングデータに基づいてメッセージを割り当てます。 各キューは特定のコンシューマーにバインドされています。 次いで、各コンシューマは、取得メッセージ> サブミットオフセット> 永続オフセットの消費セマンティクスに従ってメッセージを処理する。 消費者がメッセージを取得しても、消費ステータスはキューに返されません。 したがって、複数のコンシューマによるメッセージの繰り返し消費を回避するために、各キューは1つのコンシューマのみによって消費され得る。
キューベースの負荷分散は、キューが1つのコンシューマのみによって処理されることを保証します。 ただし、このポリシーの実装は、消費者とブローカーの間の情報交渉メカニズムに依存します。 ApsaraMQ for RocketMQは、キュー内のメッセージが1つのコンシューマーのみによって処理されることを保証するものではありません。 そのため、コンシューマ数やキュー数が変化すると、キューの割り当てに一時的な不整合が生じ、少数のメッセージが複数回処理されることになる。
特徴
メッセージベースのロードバランシングと比較して、キューベースのロードバランシングの粒度は大きく、柔軟性が低くなります。 ただし、キューベースの負荷分散は、ストリーム処理シナリオに最適です。 キュー内のメッセージが1つのコンシューマーによって処理されるようにします。 したがって、キューベースの負荷分散は、集約されたメッセージまたはメッセージをバッチで処理するシナリオに適しています。
シナリオ
キューベースの負荷分散は、集約されたメッセージまたはメッセージをバッチで処理するシナリオに適用できます。 これらは、ストリームコンピューティングおよびデータ集約アプリケーションの一般的なシナリオです。
例:
コンシューマは、キューベースの負荷分散のために追加の設定を実行する必要はありません。 デフォルトでは、このポリシーはブローカーバージョン4.xおよび3.xのプルコンシューマーに対して有効になっています。
サンプルコードの詳細については、Apache RocketMQのコードライブラリを参照してください。
バージョンの互換性
メッセージベースの負荷分散ポリシーは、ApsaraMQ for RocketMQのブローカーバージョン5.0から入手できます。 ブローカーバージョン4.xおよび3.xでは、キューベースの負荷分散ポリシーのみが使用できます。
ブローカーバージョン5.xのApsaraMQ for RocketMQでは、メッセージベースとキューベースの両方の負荷分散ポリシーを使用できます。 どのポリシーが有効かは、クライアントのバージョンとコンシューマーの種類によって異なります。
使用上の注意
消費ロジックにメッセージべき等性を実装します。
メッセージベースとキューベースの両方の負荷分散ポリシーは、コンシューマーの追加、コンシューマーの削除、ブローカースケーリングなどのシナリオで一時的な再分散をトリガーします。 これにより、一時的な負荷の不整合が生じ、少数のメッセージが2回以上消費される可能性があります。 したがって、メッセージ消費のべき等性を確保するために重複排除を行う必要がある。