繁体   English   中英

KafkaListener 监听多个主题时,能否优先考虑单个主题?

[英]Can you give priority to a single topic when KafkaListener listens to multiple topics?

当我的@KafkaListener 监听多个主题时,任何人都知道如何优先考虑单个 kafka 主题?

在我的代码示例下面:

@KafkaListener(id = "priority", topics = { "${prio-topic}" }, concurrency = "1", autoStartup = "true")
    @KafkaListener(id = "nonPriority", topics = { "${not-prio-topic-1}",
            "${not-prio-topic-2}", "${not-prio-topic-3}",
            "${not-prio-topic-4}", concurrency = "1", autoStartup = "true")
    public synchronized void  listenManyEntryTopic(String message) {}

我的问题是我想在其他 nonPrio 主题之前阅读主题 prio prio-topic 只有当我的prio-topic为空时,我才应该开始使用其他没有任何特定顺序的主题。 任何提示/建议表示赞赏。 谢谢您的帮助!

kafka 中没有区分优先级和非优先级主题消息的功能。 为了解决您的问题,解决方案之一是将优先处理主题与非优先主题分开,即专用 app1 仅使用优先主题消息并处理它们,同时 app2 使用非优先消息并处理它们。

由于您有两个侦听器容器,因此您可以将@Header(KafkaHeaders.RECEIVED_TOPIC) String topic作为参数添加到您的方法中。

然后,当您收到来自优先主题的消息时,您可以stop()另一个侦听器容器(使用KafkaListenerEndpointRegistry bean),如果它正在运行。

在主主题容器中配置idleEventInterval并为ListenerContainerIdleEvent s(或ApplicationListener bean)添加一个@EventListner方法。

然后,当您检测到空闲的主容器时,您可以重新启动非主容器。

编辑

@SpringBootApplication
public class So66366140Application {

    private static final Logger LOG = LoggerFactory.getLogger(So66366140Application.class);

    public static void main(String[] args) {
        SpringApplication.run(So66366140Application.class, args);
    }

    @Bean
    public NewTopic topic1() {
        return TopicBuilder.name("so66366140-1").partitions(1).replicas(1).build();
    }

    @Bean
    public NewTopic topic2() {
        return TopicBuilder.name("so66366140-2").partitions(1).replicas(1).build();
    }

    @Autowired
    KafkaListenerEndpointRegistry registry;

    @KafkaListener(id = "so66366140-1", topics = "so66366140-1")
    @KafkaListener(id = "so66366140-2", topics = "so66366140-2", autoStartup = "false")
    public void listen(String in, @Header(KafkaHeaders.RECEIVED_TOPIC) String topic) {
        LOG.info(in);
        if (topic.equals("so66366140-1")
                && this.registry.getListenerContainer("so66366140-2").isRunning()) {
            LOG.info("Stopping non-pri container");
            this.registry.getListenerContainer("so66366140-2").stop();
        }
    }

    @EventListener
    void events(ListenerContainerIdleEvent event) {
        LOG.info(event.toString());
        if (event.getListenerId().startsWith("so66366140-1")
                && !this.registry.getListenerContainer("so66366140-2").isRunning()) {
            LOG.info("Starting non-pri container");
            this.registry.getListenerContainer("so66366140-2").start();
        }
    }

    @Bean
    public ApplicationRunner runner(KafkaTemplate<String, String> template) {
        return args -> {
            IntStream.range(0,  10).forEach(i -> {
                template.send("so66366140-1", "foo");
                template.send("so66366140-2", "bar");
                try {
                    Thread.sleep(6_000);
                }
                catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        };
    }

}
spring.kafka.consumer.auto-offset-reset=earliest
spring.kafka.listener.idle-event-interval=5s

您也可以使用暂停/恢复而不是停止/开始。

暂无
暂无

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

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