我当时正在分析创建通用消费者库的问题,该消费者库可以部署在多个微服务中(所有这些服务都是基于spring的)。要求大约有15-20个主题。如果我们使用基于注释的kafka监听器,则需要为每个微服务添加更多代码。有什么方法可以基于某个xml文件动态创建使用者,每个使用者都可以注入这些数据
带有批注的设计非常僵化。我能想到的唯一方法是,我们可以在解析xml配置后创建messagelistener,并且每个主题都有自己的并发messagelistenercontainer。
使用spring还有其他更好的方法吗?
P.S:我对spring&kafka并不陌生。请让我知道在解释要求方面是否有困惑
谢谢, 拉贾塞卡尔
答案 0 :(得分:3)
也许您可以使用主题模式。看一下consumer properties。例如。听众
@KafkaListener(topicPattern = "topic1|topic2")
将收听topic1
和topic2
。
如果您需要动态创建侦听器,则必须格外小心,因为必须将其关闭。
我将使用与spring KafkaListenerAnnotationBeanPostProcessor
类似的方法。该后处理器负责处理@KafkaListener
。
以下是有关其工作方式的建议:
public class DynamicEndpointRegistrar {
private BeanFactory beanFactory;
private KafkaListenerContainerFactory<?> containerFactory;
private KafkaListenerEndpointRegistry endpointRegistry;
private MessageHandlerMethodFactory messageHandlerMethodFactory;
public DynamicEndpointRegistrar(BeanFactory beanFactory,
KafkaListenerContainerFactory<?> containerFactory,
KafkaListenerEndpointRegistry endpointRegistry, MessageHandlerMethodFactory messageHandlerMethodFactory) {
this.beanFactory = beanFactory;
this.containerFactory = containerFactory;
this.endpointRegistry = endpointRegistry;
this.messageHandlerMethodFactory = messageHandlerMethodFactory;
}
public void registerMethodEndpoint(String endpointId, Object bean, Method method, Properties consumerProperties,
String... topics) throws Exception {
KafkaListenerEndpointRegistrar registrar = new KafkaListenerEndpointRegistrar();
registrar.setBeanFactory(beanFactory);
registrar.setContainerFactory(containerFactory);
registrar.setEndpointRegistry(endpointRegistry);
registrar.setMessageHandlerMethodFactory(messageHandlerMethodFactory);
MethodKafkaListenerEndpoint<Integer, String> endpoint = new MethodKafkaListenerEndpoint<>();
endpoint.setBeanFactory(beanFactory);
endpoint.setMessageHandlerMethodFactory(messageHandlerMethodFactory);
endpoint.setId(endpointId);
endpoint.setGroupId(consumerProperties.getProperty(ConsumerConfig.GROUP_ID_CONFIG));
endpoint.setBean(bean);
endpoint.setMethod(method);
endpoint.setConsumerProperties(consumerProperties);
endpoint.setTopics(topics);
registrar.registerEndpoint(endpoint);
registrar.afterPropertiesSet();
}
}
然后,您应该能够动态注册侦听器。例如
DynamicEndpointRegistrar dynamicEndpointRegistrar = ...;
MyConsumer myConsumer = ...; // create an instance of your consumer
Properties properties = ...; // consumer properties
// the method that should be invoked
// (the method that's normally annotated with KafkaListener)
Method method = MyConsumer.class.getDeclaredMethod("consume", String.class);
dynamicEndpointRegistrar.registerMethodEndpoint("endpointId", myConsumer, method, properties, "topic");