此问题与this相关联。
我有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)为什么每个消息集的分区信息不一致?有时没有分区信息,有时分区在同一组中重复,等等。
答案 0 :(得分:1)
仔细阅读spring-kafka文档后会发现 - &#34;了解应用程序监听器将获取所有容器的事件非常重要#34;我能够选择正确的主题和分区空闲事件基于列表器的指定分区。下面的代码似乎运行良好。
在侦听器中实现ConsumerSeekAware接口...并通过覆盖onPartitionAssigned()方法保存分配给listen的分区 -
@Override
public void onPartitionsAssigned(Map<TopicPartition, Long> assignments, ConsumerSeekCallback callback) {
assignedPartitions.clear();
assignments.forEach((topicPartition, aLong) -> assignedPartitions.add(topicPartition.partition()));
}
然后在事件监听器中,仅在涉及相关主题和分区的情况下选择事件 -
@EventListener
public void eventHandler(ListenerContainerIdleEvent event) {
Collection<TopicPartition> topicPartitions = event.getTopicPartitions();
topicPartitions.forEach(p -> {
if (p.topic().equals(yourTopicName) && assignedPartitions.contains(p.partition()))
LOG.info("No messages on partition: " + p.partition() + " topic:" + p.topic());
}
);
}
我不确定为什么在上面我的情况下,监听器被调用了4次......我期待它被调用3次,每个分区一次。我没有在生产中观察到这种行为。