发布 - 订阅频道进入Kafka导致重复的KafkaProducerContexts

时间:2016-01-05 22:03:40

标签: spring spring-integration apache-kafka kafka-producer-api

我试图使用Spring Integration将数据从一个通道发送到两个不同的Kafka队列,之后这些相同的数据在到各自队列的路上经历不同的转换。问题是我显然有重复的生成器上下文,我不知道为什么。

这是我的流程配置:

flow -> flow
        .channel(“firstChannel")
        .publishSubscribeChannel(Executors.newCachedThreadPool(), s -> s
                .subscribe(f -> f
                                .transform(firstTransformer::transform)
                                .channel(MessageChannels.queue(50))
                                .handle(Kafka.outboundChannelAdapter(kafkaConfig)
                                        .addProducer(firstMetadata(), brokerAddress), e -> e.id(“firstKafkaOutboundChannelAdapter")
                                        .autoStartup(true)
                                        .poller(p -> p.fixedDelay(1000, TimeUnit.MILLISECONDS).receiveTimeout(0).taskExecutor(taskExecutor))
                                        .get())
                )
                .subscribe(f -> f
                                .transform(secondTransformer::transform)
                                .channel(MessageChannels.queue(50))
                                .handle(Kafka.outboundChannelAdapter(kafkaConfig)
                                        .addProducer(secondMetadata(), brokerAddress), e -> e.id(“secondKafkaOutboundChannelAdapter")
                                        .autoStartup(true)
                                        .poller(p -> p.fixedDelay(1000, TimeUnit.MILLISECONDS).receiveTimeout(0).taskExecutor(taskExecutor))
                                        .get())
                ));

例外是:

无法在bean名称'not_specified'下注册对象[org.springframework.integration.kafka.support.KafkaProducerContext@3163987e]:已有对象[org.springframework.integration.kafka.support.KafkaProducerContext@15f193b8绑定

我尝试过使用不同的kafkaConfig个对象,但这没有用。同时,ProducerMetadata个实例是不同的,您可以从addProducer的不同第一个参数中看到。这些提供了各个目标队列的名称以及其他元数据。

听起来有些隐式bean定义正在创建,彼此冲突。

如何使用两个KafkaProducerContext来解决此异常?

1 个答案:

答案 0 :(得分:1)

您不应该在.get()上使用KafkaProducerMessageHandlerSpec,让框架为您设计环境。

问题是因为KafkaProducerMessageHandlerSpec implements ComponentsRegistration并且没有人关心:

public Collection<Object> getComponentsToRegister() {
    this.kafkaProducerContext.setProducerConfigurations(this.producerConfigurations);
    return Collections.<Object>singleton(this.kafkaProducerContext);
}
手动.get()调用后

我同意,这有些不便之处,我们应该为最终应用找到更好的解决方案,但是还没有选择,除非遵循框架组件的Spec样式,例如Kafka.outboundChannelAdapter()

希望我很清楚。

<强>更新

好的,这绝对是我们这方面的问题。我们很快就会解决它: https://jira.spring.io/browse/INTEXT-216 https://jira.spring.io/browse/INTEXT-217

与此同时,您的解决方法是这样的:

 KafkaProducerContext kafkaProducerContext = (KafkaProducerContext) kafkaProducerMessageHandlerSpec.getComponentsToRegister().iterator().next();
 kafkaProducerContext.setBeanName(null);

你应该搬家的地方

Kafka.outboundChannelAdapter(kafkaConfig)
                                    .addProducer(firstMetadata(), brokerAddress)

使用单独的private方法来访问kafkaProducerContext