我正在研究kafka消费者程序。最近,我们将其部署在PROD环境中。在那里,我们面临的问题如下:
[main] INFO com.cisco.kafka.consumer.RTRKafkaConsumer - No. of records fetched: 1
[kafka-coordinator-heartbeat-thread | otm-opl-group] INFO org.apache.kafka.clients.consumer.internals.AbstractCoordinator - [Consumer clientId=consumer-otm-opl-group-1, groupId=otm-opl-group] Group coordinator opl-kafka-prd2-01:9092 (id: 2147483644 rack: null) is unavailable or invalid, will attempt rediscovery
[kafka-coordinator-heartbeat-thread | otm-opl-group] INFO org.apache.kafka.clients.consumer.internals.AbstractCoordinator - [Consumer clientId=consumer-otm-opl-group-1, groupId=otm-opl-group] Discovered group coordinator opl-kafka-prd2-01:9092 (id: 2147483644 rack: null)
[kafka-coordinator-heartbeat-thread | otm-opl-group] INFO org.apache.kafka.clients.consumer.internals.AbstractCoordinator - [Consumer clientId=consumer-otm-opl-group-1, groupId=otm-opl-group] Attempt to heartbeat failed for since member id consumer-otm-opl-group-1-953dfa46-9ced-472f-b24f-36d78c6b940b is not valid.
[main] INFO com.cisco.kafka.consumer.RTRKafkaConsumer - Batch start offset: 9329428
[main] INFO com.cisco.kafka.consumer.RTRKafkaConsumer - Batch Processing Successful.
[main] INFO org.apache.kafka.clients.consumer.internals.ConsumerCoordinator - [Consumer clientId=consumer-otm-opl-group-1, groupId=otm-opl-group] Failing OffsetCommit request since the consumer is not part of an active group
Exception in thread "main" org.apache.kafka.clients.consumer.CommitFailedException: Commit cannot be completed since the group has already rebalanced and assigned the partitions to another member. This means that the time between subsequent calls to poll() was longer than the configured max.poll.interval.ms, which typically implies that the poll loop is spending too much time message processing. You can address this either by increasing max.poll.interval.ms or by reducing the maximum size of batches returned in poll() with max.poll.records.
at org.apache.kafka.clients.consumer.internals.ConsumerCoordinator.sendOffsetCommitRequest(ConsumerCoordinator.java:1061)
at org.apache.kafka.clients.consumer.internals.ConsumerCoordinator.commitOffsetsSync(ConsumerCoordinator.java:936)
at org.apache.kafka.clients.consumer.KafkaConsumer.commitSync(KafkaConsumer.java:1387)
at org.apache.kafka.clients.consumer.KafkaConsumer.commitSync(KafkaConsumer.java:1349)
at com.cisco.kafka.consumer.RTRKafkaConsumer.main(RTRKafkaConsumer.java:72)
我的理解是,当组协调器不可用并被重新发现时,心跳间隔(根据文档为3秒)到期并且消费者被踢出了组。这个对吗?。如果是这样,应该如何解决?如果我错了,请帮助我理解此问题,并提出解决此问题的建议。如果需要,我可以共享代码。
答案 0 :(得分:3)
您所指的异常
Exception in thread "main" org.apache.kafka.clients.consumer.CommitFailedException: Commit cannot be completed since the group has already rebalanced and assigned the partitions to another member. This means that the time between subsequent calls to poll() was longer than the configured max.poll.interval.ms, which typically implies that the poll loop is spending too much time message processing. You can address this either by increasing max.poll.interval.ms or by reducing the maximum size of batches returned in poll() with max.poll.records.
提示正在发生的事情以及可以解决该问题的方法。在code中,此异常描述为
“当使用KafkaConsumer#commitSync()的偏移提交失败并出现不可恢复的错误时,将引发此异常。当在成功应用提交之前完成组重新平衡时,可能会发生这种情况。在这种情况下,通常无法重试该提交因为某些分区可能已经分配给该组中的另一个成员。”
以我的经验,引发错误消息的原因可能是不同的,尽管它们都与不再分配给使用者的消费者有关:
如果将消费者添加到现有的ConsumerGroup,则会发生重新平衡。因此,必须在使用后关闭使用者或始终使用同一实例,而不是为每个消息/迭代创建新的KafkaConsumer对象。
[...],随后对poll()的调用之间的时间比已配置的
max.poll.interval.ms
更长,这通常意味着轮询循环在消息处理上花费了太多时间。
配置 max.poll.interval.ms 默认为300000ms
或5minutes
。由于您的使用者花费了超过5分钟的时间,因此该使用者被视为失败,该组将重新平衡以将分区重新分配给另一个成员(请参见Consumer Configuration)。
错误消息中也给出了可能的解决方案
您可以通过增加
max.poll.interval.ms
或通过使用max.poll.records
减小poll()中返回的批处理的最大大小来解决此问题。
使用者再次读取所有消息,因为(如错误所示)它无法提交偏移量。这意味着,如果您使用相同的group.id
来启动Consumer,它会认为它永远不会从该主题中读取任何内容。
KafkaConsumer中有两个主要配置可处理心跳:heartbeat.interval.ms
和session.timeout.ms
。
在单独的后台线程中,您的KafkaConsumer将定期的心跳发送到服务器。如果使用者在session.timeout.ms期间崩溃或无法发送心跳,则该使用者将被视为已死,并且将重新分配其分区。如果触发了重新平衡,则您的用户将无法从“旧分配”分区中提交任何内容,就像在CommitFailedException的描述中所写的那样:“当成功完成提交之前,组重新平衡完成时,可能会发生这种情况。” >
在遵循建议的同时增加设置heartbeat.interval.ms
和session.timeout.ms
:“ heartbeat.interval.ms
必须设置为低于session.timeout.ms
,但通常不应设置为1 /该值的3。”
请记住,更改这些值总是需要权衡取舍。你有
在生产集群上,在应用程序无法续订Kerberos票证之后,我们已经看到了CommitFailedException。
答案 1 :(得分:0)
我们遇到了类似的问题,我们通过将默认轮询记录的最大轮询记录减少了500,并且还缩短了心跳间隔来解决此问题。如果您的消息处理需要时间并且轮询记录为500,则获得CommitFailedException的可能性很高。