我有Kafka topic
1-partition
。 1 listener
在我的spring-boot应用中使用@KafkaListener
定义。 listener
使用ThreadPoolTaskExecutor
选择ConsumerRecord
并对其进行处理。但是,我可以看到kafka承诺的严格排序,在这种情况下,因为我可以看到offset
有时跳转(使用时间戳验证)并行线程开始处理...所以问题:
编辑1
public class DefaultTopicListener {
@Autowired
ThreadPoolTaskExecutor executorPool;
@KafkaListener(topicPartitions=@TopicPartition(topic="defaultTopic",
partitions={"0"}))
public void onMessage(ConsumerRecord<String, CustomPayload> request) {
CustomPayload message = request.value();
try {
executorPool.execute(new Runnable() {
@Override
public void run() {
logger.info(
"onMessage : executorPool_THREAD_{}-> -> Offset {}.... ",
Thread.currentThread().getId(), request.offset());
}
});
} catch (RejectedExecutionException ex) {
logger.error(
"onMessage : executorPool -> Queue Full Request Rejected for offset -> {}", ex, );
}
}
public class Config {
@Bean("executorPool")
public ThreadPoolTaskExecutor executorPool(){
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(3);
executor.setMaxPoolSize(5);
executor.setQueueCapacity(5);
return executor;
}
}
请告知。
答案 0 :(得分:2)
不清楚你的意思。线程池不会选择&#34;事情,他们被赋予了运行的任务。您需要显示您的代码。
...投机
如果您的侦听器正在将ConsumerRecord
移交给线程池,那么当然,记录排序会丢失,因为记录是在不同的线程上处理的(除非池的大小为1)。
对于单个分区,侦听器容器在单个线程上调用侦听器。如果您想保留订单,则不得将工作交给其他线程。
实现并发的唯一方法是使用多个分区并增加容器的并发性。分区将分布在容器线程中。
或者,您需要在代码中管理确认,以确保没有&#34;跳转&#34;承诺。
仅在分区内保证订购,因此,您不能将其移交给另一个线程。
答案 1 :(得分:1)
Kafka通常建议每个消费者使用一个帖子。如果您想将处理与消耗分离,那么将ConsumerRecords实例移交给实际处理记录处理的处理器线程池所消耗的阻塞队列。
https://kafka.apache.org/090/javadoc/index.html?org/apache/kafka/clients/consumer/KafkaConsumer.html
然而,在这种情况下排序并不能保证,因为线程将独立执行,因为线程执行时间的好运,实际上可以在稍后的数据块之后处理较早的数据块。
订购和并行可以通过让多个分区和一个负责分区的线程来实现,分区中的所有记录都将由线程按顺序处理。