组中的 Kafka 消费者跳过分区

Posted

技术标签:

【中文标题】组中的 Kafka 消费者跳过分区【英文标题】:Kafka consumer in group skips the partitions 【发布时间】:2020-05-09 14:24:02 【问题描述】:

我有一个消费主题的消费者。主题有 6 个分区。分配给组的单个消费者。 我做如下投票 Consumer.poll(10000) 当没有记录返回时,我退出消费者获取。

从文档中,我相信当没有记录可以使用并且持续时间 10000 足以重新平衡和获取记录时,poll 返回空。 大多数时候 poll 会消耗所有分区的记录,但有时 poll 会从 3 个分区中获取记录并返回空记录而不消耗其他 3 个分区。

顺便说一句,我使用 2.0.1 Kafka 客户端,Kafka 服务器版本是 2.11 - 2.2.0。

任何人都知道为什么我的消费者会跳过其他分区并返回空记录。我应该怎么做才能消耗所有分区。

【问题讨论】:

底线:当您调用poll() 时,不能保证每次都能从所有分区获取数据,即使所有分区都有可用数据。消费者将确保认为,它通过连续调用poll() 对所有分区进行“循环”,以确保没有分区饿死。 【参考方案1】:

max.poll.records 参数默认为 500。因此,有时可能无法通过一次 poll() 获取主题中所有分区的所有消息。

ma​​x.poll.records:单次返回的最大记录数 调用 poll()。

顺便说一句,组中只有一个消费者不是使用分区消费主题的合适方式。您在消费者组中的消费者数量应等于最佳实践中订阅的主题中的分区数量。 (默认情况下,Kafka 将分区平均分配给消费者)否则您无法水平扩展负载,并且在这种情况下拥有分区并没有太大意义。

Kafka 总是为消费者分配分区。不可能有一个未分配给消费者的分区。 (如果订阅了这个主题)

但在您的情况下,因为您退出了消费者,因此需要一些时间 (session.timeout.ms) 才能将该消费者视为已被 Kafka 杀死。如果不等待session.timeout.ms通过就重新启动消费者,那么Kafka意识到消费者组中有两个活跃消费者,并为这两个消费者平均分配分区。 (比如:partition 0, 1, 2 to consumer-1,partition 3, 4, 5 to consumer-2)但是当Kafka意识到有一个consumer死掉后,在consumer group中启动rebalance,所有partition都分配给消费群体中的一位活跃消费者。

session.timeout.ms:用于检测客户端故障的超时时间 使用 Kafka 的组管理工具。客户端定期发送 心跳以向代理指示其活跃性。如果没有心跳 在此会话到期之前由经纪人收到 超时,然后代理将从组中删除该客户端,并且 启动再平衡。请注意,该值必须在允许范围内 代理配置中配置的范围 group.min.session.timeout.ms 和 group.max.session.timeout.ms

您可以在代理端使用此 cli 命令检查您的消费者组的当前分区分配:

./kafka/bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 --describe --group yourConsumerGroup

【讨论】:

是的,明白。我尝试在我的测试应用程序开始之前排空话题。所以使用单消费者但单消费者永远不会收到来自 3、4,5 分区的消息。始终分配给 0、1、2 个分区。这是预期的吗?我什至在获取零记录后继续轮询十次,可以看到重新平衡发生并分配了相同的 0、1、2 分区。 @PrabaharanKathiresan 我编辑了答案。我希望这会对你有所帮助:) 如果你对消费者调用close方法怎么办?不是马上通知离开群吗? @cricket_007 据我从 kafka 消费者 api 文档中了解到,close() 方法试图优雅地离开组,但不能保证,它也需要一些时间。当然,这仍然是阻止消费者的最佳方式。

以上是关于组中的 Kafka 消费者跳过分区的主要内容,如果未能解决你的问题,请参考以下文章

kafka——消费者原理解析

kafka 如何决定单个消费者组中哪个消费者读取消息?

每月摘录202003

Kafka & NSQ

五 通过命令行了解 Kafka消费者组

Kafka--04---Kafka集群操作