如何检测spring kafka使用者何时停止从1个分区获取消息?

时间:2017-12-09 20:02:17

标签: apache-kafka spring-kafka

我有3个春天kafka消费者(同一组)从3个分区获取消息。我想检测其中一个消费者何时停止从1个分区读取(其他2个消费者继续从其他2个分区读取)。到目前为止,这已经发生过两次,当检测到时,通过重新启动导致重新平衡的所有消费者很容易解决。问题是在两种情况下,早先知道它会很好。所以我尝试使用ListenerContainerIdleEvent,如此 -

@EventListener
public void eventHandler(ListenerContainerIdleEvent event) {
    LOG.info("idle event fired! listnerId=" + event.getListenerId());

    Collection<org.apache.kafka.common.TopicPartition> partitions = event.getTopicPartitions();
    partitions.forEach(p ->
            LOG.info("partition: " + p.partition() + " topic:" + p.topic()));
}

以下是我的测试结果 -

  

1)1个消费者从1个分区读取,此事件运作良好。

     

2)1个消费者从3个分区读取,此事件仅被调用   什么时候所有3个分区都没有消息。如果没有消息   1或2个分区,但第3个分区上有消息,这个   事件不会被调用。

当将消费者分配到多个分区时,是否有一种方法可以在1个分区中读取消息(无论出于何种原因......消费者问题或无法从分区读取消息)时收到通知?

更新:03/27/2018

我不确定是否应该提出与此相关的新问题,以便首先尝试扩展此问题。我有1个消费者从1个主题和3个分区消费。我已经设置了idleEventInterval = 30secs。每隔30秒,我会收到以下日志消息。

  

12:12:51.517 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.t.m.e.s.e.p.k.InboundMessageHandler - 没有收到30855毫秒的消息   12:12:51.517 [org.springframework.kafka.KafkaListenerEndpointContainer#1-0-C-1] INFO c.t.m.e.s.e.p.k.InboundMessageHandler - 没有收到30845毫秒的消息   12:12:51.517 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.t.m.e.s.e.p.k.InboundMessageHandler - partition:1 topic:test-topic   12:12:51.517 [org.springframework.kafka.KafkaListenerEndpointContainer#1-0-C-1] INFO c.t.m.e.s.e.p.k.InboundMessageHandler - partition:2 topic:test-topic   12:12:51.517 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.t.m.e.s.e.p.k.InboundMessageHandler - partition:0 topic:test-topic   12:12:51.517 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.t.m.e.s.e.p.k.InboundMessageHandler - 没有收到30855毫秒的消息   12:12:51.517 [org.springframework.kafka.KafkaListenerEndpointContainer#1-0-C-1] INFO c.t.m.e.s.e.p.k.InboundMessageHandler - 没有收到30845毫秒的消息   12:12:51.517 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.t.m.e.s.e.p.k.InboundMessageHandler - partition:1 topic:test-topic   12:12:51.517 [org.springframework.kafka.KafkaListenerEndpointContainer#1-0-C-1] INFO c.t.m.e.s.e.p.k.InboundMessageHandler - partition:2 topic:test-topic   12:12:51.517 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.t.m.e.s.e.p.k.InboundMessageHandler - partition:0 topic:test-topic

     

12:13:21.630 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.t.m.e.s.e.p.k.InboundMessageHandler - 没有收到60977毫秒的消息   12:13:21.630 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.t.m.e.s.e.p.k.InboundMessageHandler - partition:1 topic:test-topic   12:13:21.630 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.t.m.e.s.e.p.k.InboundMessageHandler - partition:0 topic:test-topic   12:13:21.630 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.t.m.e.s.e.p.k.InboundMessageHandler - 没有收到60977毫秒的消息   12:13:21.630 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.t.m.e.s.e.p.k.InboundMessageHandler - partition:1 topic:test-topic   12:13:21.630 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.t.m.e.s.e.p.k.InboundMessageHandler - partition:0 topic:test-topic   12:13:21.632 [org.springframework.kafka.KafkaListenerEndpointContainer#1-0-C-1] INFO c.t.m.e.s.e.p.k.InboundMessageHandler - 没有收到60975毫秒的消息   12:13:21.632 [org.springframework.kafka.KafkaListenerEndpointContainer#1-0-C-1] INFO c.t.m.e.s.e.p.k.InboundMessageHandler - partition:2 topic:test-topic   12:13:21.633 [org.springframework.kafka.KafkaListenerEndpointContainer#1-0-C-1] INFO c.t.m.e.s.e.p.k.InboundMessageHandler - 没有收到60975毫秒的消息   12:13:21.633 [org.springframework.kafka.KafkaListenerEndpointContainer#1-0-C-1] INFO c.t.m.e.s.e.p.k.InboundMessageHandler - partition:2 topic:test-topic

事件监听器代码是 -

  @EventListener
public void eventHandler(ListenerContainerIdleEvent event) {
    LOG.info("No messages received for " + event.getIdleTime() + " milliseconds");

Collection<org.apache.kafka.common.TopicPartition> partitions = event.getTopicPartitions();
partitions.forEach(p ->
    LOG.info("partition: " + p.partition() + " topic:" + p.topic()));

}

1)为什么这个事件每30秒被调用4次?

2)为什么每个消息集的分区信息不一致?有时没有分区信息,有时分区在同一组中重复,等等。

1 个答案:

答案 0 :(得分:1)

  

...没有可从分区中读取的消息

如果并发性为1且有3个分区,则所有三个分区将由同一个使用者处理。如果为消费者分配了多个主题并且在一段时间内未收到来自特定主题的消息,则框架中当前没有任何内容可以发布事件。

如果将容器并发性增加到3,则将有3个使用者 - 每个分区一个。每个消费者如果闲置,将发布该事件。 侦听器必须是线程安全的,因为将有3个线程调用它并且通常是并发的。

显然,如果您有大量分区,这将无法很好地扩展。

  

无论出于什么原因......消费者问题......

如果主题中存在消息并且分配了该主题的消费者没有收到消息,那么这将是相当奇怪的,但该消费者正在主动接收来自其他分区的消息。这需要卡夫卡人的帮助。