我使用Spark 2.0.0和Kafka 0.10.2。
我有一个处理来自Kafka的消息的应用程序,并且是一个长期运行的工作。
我不时会在日志中看到以下消息。我理解如何增加超时,除了我想知道的一切,我确实有这个错误,我该如何从中恢复呢?
ERROR ConsumerCoordinator:偏移提交失败。 org.apache.kafka.clients.consumer.CommitFailedException:
由于该组已经重新平衡并将分区分配给另一个成员,因此无法完成提交 这意味着后续调用poll()的时间长于配置的session.timeout.ms,这通常意味着轮询循环花费了太多时间进行消息处理。
您可以通过增加会话超时或通过max.poll.records减少poll()中返回的批量的最大大小来解决此问题。
这不是我如何逃避这个错误,而是如何处理它
背景:在正常情况下,我不会看到提交错误,但如果我确实得到了错误,我应该能够从中恢复。我正在使用AT_LEAST_ONCE
设置,所以我对重新处理一些消息感到非常满意。
我正在运行Java并使用DirectKakfaStreams进行手动提交。
创建流:
JavaInputDStream<ConsumerRecord<String, String>> directKafkaStream =
KafkaUtils.createDirectStream(
jssc,
LocationStrategies.PreferConsistent(),
ConsumerStrategies.<String, String>Subscribe(topics, kafkaParams));
提交抵消
((CanCommitOffsets) directKafkaStream.inputDStream()).commitAsync(offsetRanges);
答案 0 :(得分:1)
我对情况的理解是您使用Kafka Direct Stream集成(使用Spark Streaming + Kafka Integration Guide (Kafka broker version 0.10.0 or higher)中所述的spark-streaming-kafka-0-10_2.11
模块。)
如错误消息中所述:
无法完成提交,因为该组已经重新平衡并将分区分配给另一个成员。
Kafka管理消费者消费的主题分区,因此Direct Stream将创建一个消费者池(在单个消费者群体中)。
与任何消费者群体一样,您应该期待重新平衡(引用第4章“卡夫卡消费者 - 从卡夫卡读取数据”来自Kafka: The Definitive Guide):
消费者组中的消费者在他们订阅的主题中共享分区的所有权。当我们向该组添加新的使用者时,它开始消耗以前由另一个使用者消费的分区的消息。当消费者关闭或崩溃,它离开组时,同样的事情发生,它过去消耗的分区将由其余的消费者消耗。当消费者组正在消费的主题被修改时,例如管理员添加新分区时,也会将分区重新分配给消费者。
在很多情况下,重新平衡可能发生并且应该是预期的。你做到了。
你问:
我该如何从中恢复?这不是我如何逃避这个错误,而是如何处理它一旦发生?
我的回答是使用CanCommitOffsets
的其他方法:
def commitAsync(offsetRanges: Array[OffsetRange], callback: OffsetCommitCallback): Unit
可让您访问Kafka的OffsetCommitCallback:
OffsetCommitCallback 是一个回调接口,用户可以实现在提交请求完成时触发自定义操作。回调可以在调用poll()的任何线程中执行。
我认为onComplete
可以帮助您了解异步提交的完成方式并采取相应措施。
我无法帮助你的是如何在某些偏移无法提交时恢复Spark Streaming应用程序中的更改。我认为需要跟踪偏移并接受一些无法提交和重新处理某些偏移的情况。