web-dev-qa-db-ja.com

Spring Kafka失敗した場合の自動コミットオフセット

Spring Kafka 1.2.2.RELEASEを使用しています。トピックをリッスンしてドキュメントにエラスティックでインデックスを付けるコンシューマーとしてKafkaリスナーがあります。MyAuto commitoffsetプロパティはtrue // defaultに設定されています。

リスナーに例外がある場合(エラスティックがダウンしている場合)、オフセットをコミットしてはならず、次のポーリングのために同じメッセージを処理する必要があるという印象を受けました。

ただし、これは発生しておらず、コンシューマーは次のポーリングでオフセットをコミットします。投稿とドキュメントを読んだ後、自動コミットをtrueに設定すると、次のポーリングですべてのオフセットがコミットされることがわかりました。

私の疑問は、コンシューマーが次のポーリングを呼び出す理由と、自動コミットをtrueに設定してオフセットがコミットされないようにする方法、またはこのプロパティをfalseに設定して手動でコミットする必要がある理由です。

6
rishi

私はそれをfalseに設定することを好みます。コンテナがオフセットを管理する方が信頼性が高くなります。

コンテナのAckModeRECORD(デフォルトはBATCH)に設定すると、リスナーが戻った後、コンテナはオフセットをコミットします。

また、少なくとも1.3.3(現在のバージョンは2.1.4)にアップグレードすることを検討してください。 1.3.xは、 KIP-62 のおかげで、はるかに単純なスレッドモデルを導入しました。

[〜#〜]編集[〜#〜]

自動コミットを使用すると、成功/失敗に関係なくオフセットがコミットされます。 ackOnErrorがtrueでない限り、コンテナーは失敗後にコミットしません(自動コミットを使用しないもう1つの理由)。

ただし、ブローカーが同じレコードを再度送信することはないため、それでも役に立ちません。そのためには、Consumerでシーク操作を実行する必要があります。

2.0.1(現在のバージョンは2.1.4)で、SeekToCurrentErrorHandlerを追加しました。これにより、失敗した未処理のレコードが次のポーリングで再送信されます。 リファレンスマニュアルを参照

ConsumerAwareListenerを使用して、自分でシークを実行することもできます(2.0でも追加されています)。

古いバージョン(> = 1.1)では、ConsumerSeekAwareリスナーを使用する必要があります。これは かなり複雑です です。

もう1つの方法は、 retry を追加して、再試行設定に従って配信が再試行されるようにすることです。

6
Gary Russell

どうやら、Spring Kafka <= 1.3.3 @KafkaListenerを使用しても、Spring Kafkaが自動的に(少なくともドキュメント)再試行して「単に再度ポーリングを行わない」ことでこれを処理しますか?:)そして、デフォルトの動作は単にログに記録することです。

Spring-kafka 1.3.3.RELEASE(Mavenソースなし)および単一のパーティショントピック、concurrency(1)、AckOnError(false)、AckModeを使用したBatchListener(true)を使用しても、コンシューマーでメッセージの損失/スキップを再現できました。 (BATCH)実行時の例外。テンプレート内で再試行するか、ConsumerSeekAwareを探索することになりました。

@GaryRussellは、「ブローカーは同じレコードを再度送信しない」またはコミットせずにメッセージの次のバッチを返し続けるのですか?これは、消費者の投票が、最後に正確にではなく、レコードの次のバッチを取得しようとした現在のオフセットに基づいているためですコミットされたオフセット?基本的に、コンシューマーは、すべての処理でいくつかの実行時例外を想定してコミットする必要はまったくなく、トピックに関するメッセージ全体を消費し続けます。最後にコミットされたオフセット(重複)から再起動のみが開始されます。

ConsumerAwareListenerErrorHandlerを使用するために2.0以降にアップグレードするには、メジャーアップグレードである少なくともSpring5.xにアップグレードする必要があるようです。

1
kisna