我正在使用@KafkaListener和ConcurrentKafkaListenerContainerFactory收听3个kafka主题,每个主题都有10个分区。我对此有几个疑问。
ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory(
ConsumerFactory<String, String> consumerFactory) {
ConcurrentKafkaListenerContainerFactory<String, String> factory =
new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(consumerFactory);
factory.setConcurrency(30);
factory.getContainerProperties().setSyncCommits(true);
return factory;
}
@KafkaListener(topics = "topic1", containerFactory="kafkaListenerContainerFactory")
public void handleMessage(final ConsumerRecord<Object, String> arg0) throws Exception {
}
@KafkaListener(topics = "topic2", containerFactory="kafkaListenerContainerFactory")
public void handleMessage(final ConsumerRecord<Object, String> arg0) throws Exception {
}
@KafkaListener(topics = "topic3", containerFactory="kafkaListenerContainerFactory")
public void handleMessage(final ConsumerRecord<Object, String> arg0) throws Exception {
}
我的listener.ackmode为 return ,并将enable.auto.commit设置为 false 和partition.assignment.strategy: org.apache.kafka.clients .consumer.RoundRobinAssignor
1)我对并发的理解是,由于我将并发(在工厂级别)设置为30,并且我总共有30个分区(对于所有三个主题)可以读取,因此每个线程将被分配一个分区。我的理解正确吗?如果我再次在@KafkaListener批注内重写并发性,会产生什么影响?
2)当spring调用poll()方法时,是否从所有三个主题中进行轮询?
3)由于我将listener.ackmode设置为return,它将发出一个下一个poll()之前一直等到在单个poll()中返回的所有记录都完成了吗?如果我的记录花费的时间超过max.poll.interval.ms,还会发生什么呢?可以说,在单个poll()调用中返回了1-100个偏移量,并且我的代码只能在max.poll.interval.ms被命中之前处理50个,由于它已经命中了max.poll,因此此时将发出另一个民意测验.interval.ms?如果是这样,下一个poll()是否将从偏移量51返回记录?
非常感谢您的时间和帮助
答案 0 :(得分:1)
我的listener.ackmode返回
没有这样的ackmode;由于您没有在出厂时进行设置,因此您的实际确认模式为BATCH(默认)。要使用ack模式记录(如果这就是您的意思),则必须配置工厂容器属性。
我对并发的理解是...
您的理解不正确;并发不能大于分区中主题最多的分区的数量(如果侦听器收听多个主题)。由于每个主题中只有10个分区,因此实际并发为10。
在侦听器上覆盖concurrency
只会覆盖出厂设置;您总是至少需要与并发一样多的分区。
spring调用poll()方法时,是否从所有三个主题中进行轮询?
不具有该配置;您有3个并发容器,每个容器有30个消费者在听一个主题。您有90个消费者。
如果所有3个主题都只有一个侦听器,则民意调查将返回所有3个主题的记录;但您仍然可能有20个空闲的使用者,具体取决于分区分配器如何分配分区-有关分区的确切分配方式,请参见日志“分配的分区”。循环分配器应将它们分配好。
此时将在春季进行另一次民意调查
Spring无法控制-如果花费的时间太长,则Consumer线程位于侦听器中-Consumer不是线程安全的,因此我们无法发出异步轮询。
您必须在max.poll.records
中处理max.poll.interval.ms
,以避免Kafka重新平衡分区。
ack模式没有区别;都是为了及时处理民意调查结果。