繁体   English   中英

如何在不同线程中处理 @KafkaListener 方法?

[英]How can I process @KafkaListener method in different threads?

我在 Spring Boot 中有 kafka 处理程序:

    @KafkaListener(topics = "topic-one", groupId = "response")
    public void listen(String response) {
        myService.processResponse(response);
    }

例如生产者每秒发送一条消息。 myService.processResponse工作 10 秒。 我需要处理每条消息并在新线程中启动myService.processResponse 我可以创建我的执行程序并将每个响应委托给它。 但我认为 kafka 中还有另一种配置。 我发现了2:

1) 将concurrency = "5"添加到@KafkaListener注释 - 它似乎有效。 但我不确定有多正确,因为我有第二种方法:

2)我可以创建ConcurrentKafkaListenerContainerFactory并将其设置为ConsumerFactoryconcurrency

我不明白这些方法的区别? 仅将concurrency = "5"添加到@KafkaListener注释就足够了,或者我需要创建ConcurrentKafkaListenerContainerFactory吗?

或者我什么都不明白,还有其他方法吗?

使用执行器会使管理偏移量变得复杂。 不推荐。

使用@KafkaListener ,框架为您创建一个ConcurrentKafkaListenerContainerFactory

批注上的concurrency只是一种方便; 它会覆盖出厂设置。

这使您可以将同一工厂与多个侦听器一起使用,每个侦听器具有不同的并发性。

您可以使用引导属性设置容器并发性(默认)。 该值被注释值覆盖; 见javadocs ...

/**
 * Override the container factory's {@code concurrency} setting for this listener. May
 * be a property placeholder or SpEL expression that evaluates to a {@link Number}, in
 * which case {@link Number#intValue()} is used to obtain the value.
 * <p>SpEL {@code #{...}} and property place holders {@code ${...}} are supported.
 * @return the concurrency.
 * @since 2.2
 */
String concurrency() default "";

concurrency选项与并发处理同一使用者接收到的消息无关。 当您有多个使用者分别处理各自的分区时,它适用于使用者组。

将处理传递到单独的线程非常复杂,我相信Spring-Kafka团队决定不“按设计”执行该操作。 您甚至无需深入研究Spring-Kafka即可了解原因。 检查KafkaConsumer的“ 检测消费者故障”文档:

必须注意确保承诺的偏移量不超过实际位置。 通常,只有在线程完成对记录的处理后,才必须禁用自动提交并手动提交记录的处理偏移量(取决于所需的传递语义)。 还要注意,您将需要暂停分区,以便在线程完成处理之前返回的记录之前,不会从轮询中接收到任何新记录。

您需要myService.processResponse(response); 方法异步。

为此,您只需要这样做:

@Async
public void processResponse(String response) {
    // Process here
}

另外,您需要通过在主类顶部添加@EnableAsync来启用异步功能。

@SpringBootApplication
@EnableAsync
public class Application {

    public static void main(String[] args) {
        // close the application context to shut down the custom ExecutorService
        SpringApplication.run(Application.class, args).close();
    }

    @Bean
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(2);
        executor.setMaxPoolSize(2);
        executor.setQueueCapacity(500);
        executor.setThreadNamePrefix("GithubLookup-");
        executor.initialize();
        return executor;
    }
}

如果您有任何问题,请查看该链接

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM