为什么kafka消费者会消耗数百条相同的消息?

时间:2018-08-07 23:04:51

标签: apache-kafka

我从日志中看到665次使用了完全相同的消息。为什么会这样?

我也在日志中看到了

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 session.timeout.ms, which typically implies 
that the poll loop is spending too much time message processing. You can address this either by increasing the session 
timeout or by reducing the maximum size of batches returned in poll() with max.poll.records.

消费者属性

group.id=someGroupId
bootstrap.servers=kafka:9092
enable.auto.commit=false
key.deserializer=org.apache.kafka.common.serialization.StringDeserializer
value.deserializer=org.apache.kafka.common.serialization.StringDeserializer
session.timeout.ms=30000
max.poll.records=20

PS:是否可以仅使用特定数量的消息,例如队列中1000条消息中的10或50或100条消息? 我当时正在查看“ fetch.max.bytes”配置,但似乎它是针对邮件大小而不是邮件数。

谢谢

2 个答案:

答案 0 :(得分:2)

答案在于对以下概念的理解:

  • session.timeout.ms
  • 心跳
  • max.poll.interval.ms

在您的情况下,您的使用者通过poll()收到一条消息,但无法在max.poll.interval.ms时间内完成处理。因此,假定代理将其挂起,并且发生分区的重新平衡,因此该使用者失去了所有分区的所有权。它被标记为已失效,并且不再属于消费者组。

然后,当您的使用者完成处理并再次调用poll()时,会发生两件事:

  1. 提交失败,因为使用者不再拥有分区。
  2. 经纪人识别出该消费方再次启动,因此触发了重新平衡,该消费方再次加入消费方组,开始拥有分区并向中介请求消息。由于先前的消息未标记为已提交(请参阅上面的#1,提交失败),并且正在等待处理,因此代理再次将相同的消息传递给使用者。

消费者再次花费大量时间来处理,并且由于无法在少于max.poll.interval.ms的时间内完成处理,因此1.和2.不断循环重复。

为解决此问题,您可以根据消费者需要处理的时间,将max.poll.interval.ms增加到足够大的值。这样,您的使用者将不会被标记为已死,也不会收到重复的消息。 但是,真正的解决方法是检查您的处理逻辑并尝试减少处理时间。

答案 1 :(得分:1)

您粘贴的消息中描述了此修复程序:

  

您可以通过增加会话超时时间或通过   减少使用poll()返回的批处理的最大大小   最大投票记录。

原因是您的使用者能够处理和提交消息之前,已达到超时。当您的Kafka使用者“提交”时,它基本上是在确认收到前一条消息,提前偏移量,因此移至下一条消息。但是,如果超时(如您的情况)过去了,那么消费者的提交将无效,因为它发生得太迟了;然后下一次消费者要求发送一条消息时,会收到相同的消息

您的一些选择是:

  1. 增加session.timeout.ms=30000,从而使消费者有更多时间 处理消息
  2. 减少max.poll.records=20,以使使用者在超时之前需要处理的消息更少。但这实际上并不适用于您,因为您的使用者已经只在处理一条消息
  3. 或者打开enable.auto.commit,这对于您来说也不是最好的解决方案,因为它可能会导致删除消息,如下所述:
      

    如果像前面的示例一样允许偏移量自动提交   消息由   消费者,并且我们的流程有可能在失败后失败   我们已经将消息读取到内存缓冲区中,但在此之前,   被插入数据库。   来源:https://kafka.apache.org/090/javadoc/org/apache/kafka/clients/consumer/KafkaConsumer.html