Clarify support for manual ack/nack with batch mode + DLQ; potential bug in acknowledge(index) path
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 初心者へのやさしさ
- 48/100
- issue の種類
- バグ
- 明瞭さ
- おおむね明確
- 活発さ
- 活発
- 技術スタック
- docker, docker-compose, java, kafka, spring-boot
調査の方向性
公開されている demoSCSKafka の repro、その src/main/resources/application.yml にある関数選択、および src/main/resources/compose/docker-compose.yml から始めます。batch-consumer-DLQ シナリオを実行し、Kafka UI を調べます。インデックス 20 で強制的に発生させる失敗の前後における acknowledge(index)、nack(index, Duration)、および BatchListenerFailedException(index) の動作を比較します。対応している manual-ack の動作が文書化され、報告されたインデックスオーバーフローと回避可能な DLQ の増幅が解決されるか、明示的にスコープ設定されれば完了です。
索引モデルが issue の本文から書いたものです。
説明
Describe the issue
We found potential issues when using Spring Cloud Stream Kafka Binder with batch consumers + DLQ + manual acknowledgments.
According to the docs, in batch mode with DLQ enabled, all records from the previous poll are sent to DLQ. That matches current behavior.
However, in manual-ack scenarios we observed:
- A likely bug with partial commits using
acknowledge(index)+ DLQ. - A general improvement opportunity: DLQ handling appears to ignore already acknowledged/committed progress and republishes records that were already processed successfully.
Repro project (public): https://github.com/ferblaca/demoSCSKafka/tree/batch-consumer-dlq
To Reproduce
- Clone and open the repro project:
git clone -b batch-consumer-dlq https://github.com/ferblaca/demoSCSKafka.git
cd demoSCSKafka
- Start Kafka/Zookeeper/Kafka UI using the provided compose file:
docker compose -f src/main/resources/compose/docker-compose.yml up -d
-
In
src/main/resources/application.yml, set one function definition at a time:batchConsumerAckManual(scenario A)batchConsumerNackManual(scenario B)
-
Run the application.
-
Produce 100 records to
input-topic-batch(the project includes the producer bindingfoo-out-0to that topic, per config). -
In the batch consumer logic, force an exception at index 20.
-
Inspect topic/DLQ behavior in Kafka UI:
http://localhost:9090
Scenario A: acknowledge(index) (partial commit) + DLQ
Observed:
- After calling
acknowledgment.acknowledge(19), the internal partial state is set (partial=19). - During DLQ handling for the failed batch, acknowledgments continue over the full polled batch.
- The failure starts when processing approximately record 80/100, because the effective index reaches 100 (
80 + partial(19) + 1 = 100), which exceeds the batch bounds. - Then it throws:
IllegalArgumentException: index (100) is out of range (0-99) - The batch is retried multiple times.
- Final DLQ count becomes much larger than input (observed: 810 (10 retries x 81 messages) DLQ records for 100 input records).
Consumer behavior:
- Partial ack every 20 records:
acknowledgment.acknowledge(i) - Forced exception at
i == 20
Observed:
- After partial ack (
acknowledge(19)), internal partial state is set. - During DLQ flow for the failed batch, an index overflow occurs:
IllegalArgumentException: index (100) is out of range (0-99) - Batch is retried multiple times.
- Final DLQ count is much larger than input (observed: 810 DLQ records for 100 input records).
This looks like a bug in the interaction between partial batch ack state and DLQ processing:
Caused by: java.lang.IllegalArgumentException: index (100) is out of range (0-99)
Scenario B: nack(index, Duration) + DLQ
Same batch/DLQ/manual setup, but using:
acknowledgment.nack(i, Duration.ofMillis(100))on failure at index 20
Observed:
- No index out-of-range exception in this path.
- But DLQ still receives records in repeated waves as re-seek/retry progresses.
- Final DLQ count is also amplified (observed: 280 DLQ records for 100 input records).
Expected behavior
- Clarify/document whether manual ack (
acknowledge/nack) is officially supported with DLQ in batch mode. - If supported, fix the apparent bug for
acknowledge(index)+ DLQ (index out-of-range). - Improve DLQ error handling so that records already acknowledged/committed are not resent to DLQ (or provide a configurable strategy), reducing duplicate DLQ traffic and unnecessary reprocessing.
Additional context
- We understand Kafka processing is at-least-once and consumers must handle duplicates.
- Even so, current behavior appears to produce avoidable DLQ amplification in manual-ack batch use cases.
- We also ask for guidance on recommended patterns when using:
acknowledge(index)nack(index, Duration)BatchListenerFailedException(index)
together with DLQ in batch mode.
Version of the framework
- Spring Cloud: 2025.1.1
- Spring Boot: 4.0.2
- 主要言語
- Java
- スター
- 1.1k
- フォーク
- 647
- 平均マージ
- 2日 7時間
- マージ済み PR(30日)
- 5
環境構築
このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
spring-cloud/spring-cloud-stream のほかの issue
-
StreamBridge removing BindingProperties leads to wrong destination in ProvisioningProvider再び着手できるかも @olegz が 29 日前に担当しましたが、オープン中のプルリクエストはありません。 オープンbug
spring-cloud/spring-cloud-stream#3257 · コメント 6 件 · リアクション 2 件 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
-
StreamBridge's hashProducerProperties produces hash collisions across different binding names, causing Partition key cannot be null再び着手できるかも このイシューのプルリクエストはマージされずにクローズされました。 オープン
難易度 4/5 3〜5日 初心者へのやさしさ 48/100
spring-cloud/spring-cloud-stream#3242 · コメント 2 件 ·
メンテナーはふだん 1 日以内に返信
-
v4.3.3 no longer adds a header "TIMESTAMP" on kafka messages consumed再び着手できるかも @olegz が 60 日前に担当しましたが、オープン中のプルリクエストはありません。 オープンBackport 4.3.x bug
spring-cloud/spring-cloud-stream#3211 · コメント 3 件 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
-
KafkaBinderMetrics not updating last stable offset再び着手できるかも @olegz が 60 日前に担当しましたが、オープン中のプルリクエストはありません。 オープンbug
spring-cloud/spring-cloud-stream#3208 · コメント 4 件 · リアクション 1 件 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
-
Add RecordInterceptor support for Kafka Streams binder再び着手できるかも このイシューのプルリクエストはマージされずにクローズされました。 オープン
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
spring-cloud/spring-cloud-stream#3188 · コメント 4 件 ·
メンテナーはふだん 1 日以内に返信
spring-cloud/spring-cloud-stream の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
openhab/openhab-addons#21882 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
YunaiV/ruoyi-vue-pro#1273 ·
メンテナーはふだん 3 日以内に返信
-
難易度 1/5 1時間未満 初心者へのやさしさ 85/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
objectionary/eo#9253 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
objectionary/hone-maven-plugin#1298 ·
メンテナーはふだん 1 日以内に返信