[英]How to pass dynamic topic name to @KafkaListener(topics) from environment variable
[英]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.