Kafka コンシューマ: コンシューマ ポーリングの準備 (15)

  • メッセージを取得する前に、次のことを確認する必要があります
    • クライアントがコーディネーターに接続しました
    • コンシューマは、コーディネータによって割り当てられたパーティションを受け取ります。
  • コンシューマーがメッセージをプルするための準備
    • 接続コーディネーター
    • コンシューマ グループに参加するリクエストをコーディネータに送信し、コーディネータから割り当てられたパーティションを取得します。

1. コンシューマーがメッセージをプルする前のシーケンス

  • 消費者はコーディネーターに消費者グループへの参加を申請します。
  • サーバー側でコンシューマを管理するコーディネータがあり、コーディネータがコンシューマ グループにコンシューマを追加します。
  • コーディネーターはすべてのコンシューマにパーティションを割り当てます
  • コンシューマは、コーディネータから割り当てられたパーティションを取得します。
  • コンシューマはパーティションからメッセージをプルします

2. リクエストを送信して結果を取得する

  • 各コンシューマーは JoinGroupRequest (コンシューマー グループへの参加リクエスト) をコーディネーターに送信する必要があり、各コンシューマーは JoinGroupResponse (コンシューマー グループへの参加応答) から割り当てられたパーティションを取得します。
  • 処理の疑似コードは次のとおりです。実際のコードは、AbstractCoordinator の joinGroupIfNeeded メソッド内にあります。
// 消费者向协调者发送加入消费组的请求,并得到分配分区
// 发送 JoinGroup 请求
JoinGroupResponse joinResult = sendJoinGroupRequest();
// 获取分区
Assignment assignment = partitionAssignment(joinResult);
// 更新状态
subscriptions.assignFromSubscribed(assignment.partitions());

ここに画像の説明を挿入

  • 実際の状況では、すべてのコンシューマがコンシューマ グループに参加するのを待ってからパーティションを割り当てるアルゴリズムを実行するため、最初に返されるのは非同期オブジェクトです。
// 在异步请求对象上轮询,如果没有完成,会一直循环
RequestFuture<JoinGroupResponse> future = sendJoinGroupRequest();
client.poll(future);
Assignment assignment = partitionAssignment(future.get());

3. 消費者が消費者グループに参加する

  • ensureActiveGroup を呼び出してコンシューマ ステップに参加します
    • onJoin準備フェーズでの準備
    • リクエストを開始する sendJoinGroupRequest
    • 結合が成功した場合は onJoinComplete
// 进行加入前准备
onJoinPrepare(generation.generationId, generation.memberId);
// TODO 发送一个注册请求
joinFuture = sendJoinGroupRequest();
// 成功加入消费组
onJoinComplete(generation.generationId, generation.memberId, generation.protocol, future.value());
  • 注: リクエストが開始されたときのメンバー番号は UNKNOWN_MEMBER_ID で、最初の結合後に実際のメンバー番号が返されます。再結合またはリバランスが発生するときに実際のメンバー番号を指定する必要があります。
  • コンシューマーがコーディネーターに接続し、「コンシューマー グループに参加」リクエストを送信し、パーティションを取得するためのロジックはすべて AbstractCoordinator にあります。
public abstract class AbstractCoordinator implements Closeable {
    
    
	// 准备加入消费组
	private boolean rejoinNeeded = true;
	// 是否需要重新加入消费组
	private boolean needsJoinPrepare = true;
	protected synchronized boolean needRejoin() {
    
    
        return rejoinNeeded;
    }
	public void ensurePartitionAssignment(){
    
    
		// 根据消费者订阅状态的变量,来判断是否需要执行重新加入消费组的逻辑
		if(subscriptions.partitionsAutoAssigned())
			ensureActiveGroup();
	}
	public void ensureActiveGroup(){
    
    
		if(!needRejoin()) return;
		if (needsJoinPrepare) {
    
    
		    // 进行加入前准备
		    onJoinPrepare(generation.generationId, generation.memberId);
		    needsJoinPrepare = false;
		}
		while (needRejoin() || rejoinIncomplete()) {
    
    
			// 再次判断是否已经确定好了 coordinator
			ensureCoordinatorReady();
			// TODO 发送加入消费者请求
			RequestFuture<ByteBuffer> future = sendJoinGroupRequest();
			client.poll(future);
			if (future.succeeded()) {
    
    
                needsJoinPrepare = true;
                // 成功加入消费组
                onJoinComplete(generation.generationId, generation.memberId, generation.protocol, future.value());
            }
		}
	}
}
  • 処理を実行するパーティションに必ず割り当ててください
    • 最初の needJoinPrepare と rejoinNeeded は両方とも true であり、コンシューマーは開始時にデフォルトでコンシューマー グループに参加します。
    • needRejoin() が完了したら、まず onJoinPrepare() を呼び出して、オフセットの送信などの準備作業を実行します。
    • コンシューマ・グループに参加する前に複数の準備が行われないように、準備が完了した後に needJoinPrepare=false を変更します。
    • needRejoin() を満たし、ループ本体を実行します。リクエストを送信し、クライアントのポーリングを 1 回呼び出して結果の取得を試みます。
    • コンシューマはパーティションに割り当てられ、rejoinNeeded を false に更新し、needsJoinPrepare を true にリセットします。
  • onJoinComplete() メソッドは、コンシューマがコンシューマ グループに正常に参加し、それをパーティションに割り当てた後、サブスクリプション ステータスの needPartitionsAssigned を false に更新します。この変数は、コンシューマ グループに再参加するかどうかを決定します。
  • コンシューマーが開始すると、さまざまなイベント (パーティションの変更、コンシューマー メンバーの変更、セッション タイムアウトなど) のリスナーを ZK に登録します。登録されたイベントが発生すると、ZKRebalanceListener のリバランス操作がトリガーされます。

おすすめ

転載: blog.csdn.net/baidu_40468340/article/details/128492534