メッセージの処理が失敗した場合、同じメッセージを再度消費します


10

Confluent.Kafka .NETクライアントバージョン1.3.0を使用しています。私はドキュメントに従っています:

var consumerConfig = new ConsumerConfig
{
    BootstrapServers = "server1, server2",
    AutoOffsetReset = AutoOffsetReset.Earliest,
    EnableAutoCommit = true,
    EnableAutoOffsetStore = false,
    GroupId = this.groupId,
    SecurityProtocol = SecurityProtocol.SaslPlaintext,
    SaslMechanism = SaslMechanism.Plain,
    SaslUsername = this.kafkaUsername,
    SaslPassword = this.kafkaPassword,
};

using (var consumer = new ConsumerBuilder<Ignore, string>(consumerConfig).Build())
{
    var cancellationToken = new CancellationTokenSource();
    Console.CancelKeyPress += (_, e) =>
    {
        e.Cancel = true;
        cancellationToken.Cancel();
    };

    consumer.Subscribe("my-topic");
    while (true)
    {
        try
        {
            var consumerResult = consumer.Consume();
            // process message
            consumer.StoreOffset(consumerResult);
        }
        catch (ConsumeException e)
        {
            // log
        }
        catch (KafkaException e)
        {
            // log
        }
        catch (OperationCanceledException e)
        {
            // log
        }
    }
}

問題は、この行をコメントアウトしてもconsumer.StoreOffset(consumerResult);、次に消費したときに次の未使用メッセージを取得し続けることです。つまり、オフセットが増加し続けます。これは、ドキュメントに記載されているとおりではなく、少なくとも1つの配信です。

設定EnableAutoCommit = falseから 'EnableAutoOffsetStore = false' を設定して削除consumer.StoreOffset(consumerResult)consumer.Commit()、に置き換えても、同じ動作がCommit表示されます。つまり、をコメントアウトしても、次の未使用のメッセージが引き続き表示されます。

ここには基本的な何かが欠けているように感じますが、何が理解できません。どんな助けでもありがたいです!


メッセージはすでにkafkaの観点からアプリケーションに返されているため、コミットすると、最後にコミットされたオフセットとして保存されますが、消費は消費したかどうかに関係なく次のメッセージを返し続けます。ここであなたの期待は何ですか?コミットと消費の前後に何が起こるかを詳しく説明していただけませんか?
Sagar Veeram

シークを使用してオフセットするまで、メッセージは再フェッチされません。これは消費に影響し、メッセージはシークオフセットから返されます。
Sagar Veeram

@ user2683814私の投稿でEnableAutoCommitは、設定内容に応じて2つのシナリオについて説明しました。がEnableAutoCommit = falseあり、IのときにConsumeオフセット11のメッセージが返されたとします。メッセージの処理がスローされ続け、呼び出しCommitが行われない場合、オフセット11の同じメッセージを何度も何度も取得し続けると思っていました。
havij

いいえ、そうではありません。既にトピックにアクセスConsumeしたCommit後で、何をポーリングするか()を制御することはできませんSubscribe。シーンの背後にあるKafka(クライアントlibの場合と同様)は、アプリに送信したすべてのオフセットを維持し、Consumeそれらを線形に送信します。したがって、障害シナリオのようにメッセージを再処理するには、コードでメッセージを追跡し、メッセージをオフセットして処理を開始する必要があります。また、以前のリクエストですでに処理されている場合は、何をスキップするかを知っておく必要があります。私は.netライブラリに精通していませんが、これはカフカデザインであるため、それほど重要ではありません。
Sagar Veeram

サブスクライブと割り当ての組み合わせを使用する必要があると思います。ユースケースをサポートするには、さまざまなコンシューマーが必要になる場合があります。障害が発生した場合は、1つのコンシューマでトピックパーティションのオフセットを割り当て/シークしてメッセージを再処理し、通常の処理でサブスクライブ/消費/コミットフローを持つ別のコンシューマを使用します。
Sagar Veeram

回答:


0

コメントはまだ追加できません。Kafkaコンシューマーはメッセージをバッチで消費するため、バックグラウンドスレッドによってプリフェッチされたバッチを繰り返し処理する可能性があります

kafka utilを使用して、コンシューマーが実際にオフセットをコミットするかどうかを確認できます kafka-consumer-groups.sh

kafka-consumer-groups.sh --bootstrap-server kafka-host:9092 --group consumer_group  --describe

0

たとえば、5のように各メッセージを一定回数処理するための再試行ロジックが必要な場合があります。これらの5回の再試行中に成功しない場合は、このメッセージを別のトピックに追加して、すべてを処理できます。実際のトピックよりも優先される失敗したメッセージ。または、失敗したメッセージを同じトピックに追加して、後で他のすべてのメッセージが消費されたときにピックアップされるようにすることもできます。

5回の再試行でメッセージの処理が成功した場合は、キュー内の次のメッセージにスキップできます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.