繁体   English   中英

spring-kafka:如果我在应用程序中定义记录生产者,则Kafka使用者不会收到记录

[英]spring-kafka: Kafka consumer isn't receiving records if I define a record producer in my application

我正在使用Spring和Spring Kafka编写一个小的PoC。 我的目标是让生产者和消费者同时写信(或阅读)该主题。

我遇到一种奇怪的情况:

  • 生产者正确地产生了记录(我可以通过Python脚本使用它们)
  • 消费者未收到记录
  • 但是,如果我从代码中删除了生产者并通过另一种方法(例如,使用python脚本)生成了记录,则消费者可以正确接收记录。

以下是我的代码-与文档示例非常相似。 更确切地说,问题出在以下事实: Spring并未创建KafkaConsumerConfiguration中的bean (即,从未调用构造它们的方法)。

制片人

KafkaProducerConfiguration.java

@Configuration
public class KafkaProducerConfiguration {

    @Bean
    public KafkaTemplate<String, String> kafkaTemplate() {
        return new KafkaTemplate<>(producerFactory());
    }

    @Bean
    public ProducerFactory<String, String> producerFactory() {
        Map<String, Object> props = new HashMap<>();
        props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:32768");
        props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
        props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
        return new DefaultKafkaProducerFactory<>(props);
    }
}

MessageSender.java

@Component
public class MessageSender {
    final static private Logger log = Logger.getLogger(MessageSender.class);

    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;

    @PostConstruct
    public void onConstruct() throws InterruptedException {
        log.info("Sending messages...");
        for (int i = 0; i < 100; ++i) {
            kafkaTemplate.send("mytopic", "this is a message");
            Thread.sleep(1000);
        }
        kafkaTemplate.flush(); // NOTE: no changes if I move this call in the loop
        log.info("Done sending messages");
    }
}

消费者

KafkaConsumerConfiguration.java

@Configuration
@EnableKafka
public class KafkaConsumerConfiguration {

    @Bean
    public KafkaListenerContainerFactory<ConcurrentMessageListenerContainer<String, String>> kafkaListenerContainerFactory() {
        ConcurrentKafkaListenerContainerFactory<String, String> factory = new ConcurrentKafkaListenerContainerFactory<>();
        factory.setConsumerFactory(consumerFactory());

        return factory;
    }

    @Bean
    public ConsumerFactory<String, String> consumerFactory() {
        return new DefaultKafkaConsumerFactory<>(consumerConfigs());
    }

    @Bean
    public Map<String, Object> consumerConfigs() {
        Map<String, Object> props = new HashMap<>();
        props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:32768");
        props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
        props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
        props.put(ConsumerConfig.GROUP_ID_CONFIG, "my-service");
        return props;
    }
}

MyMessageListener.java

@Service
public class MyMessageListener {
    final static private Logger log = Logger.getLogger(MyMessageListener.class);

    @PostConstruct
    public void onConstruct() {
        log.info("Message listener started");
    }

    @KafkaListener(topics = "mytopic")
    public void onMessageReceived(String message) {
        log.info("Got message: "+ message);
    }
}

这是应用程序生成的日志,以供参考: https : //pastebin.com/BY783jiL 如您所见,没有创建消费者Bean(否则,将有一个Block ConsumerConfig values: ...

这是我尝试未成功的几件事:

  • 将生产者和使用者配置放在相同的配置类中
  • 在KafkaConsumerConfiguration中更改Bean的名称(并在MyMessageListener.onMessageReceived方法上添加注释属性containerFactory = "myBeanName"
  • 将类KafkaConsumerConfiguration的名称更改为其他名称
  • 在我的KafkaConsumerConfiguration添加与kafka不相关的@Bean ,以查看是否会创建它(确实如此)

版本:Spring Boot 1.5.9,Spring-Kafka:1.1.7。

我已经把头发扯了几个小时了,任何帮助我都感激不尽。

谢谢!

 kafkaTemplate.send("mytopic", "this is a message"); 

您永远不要开始使用@PostConstruct方法与外部服务进行交互-您需要等待构建应用程序后再进行操作。

实现SmartLifecyle ,为isAutoStartup返回true并将该代码移动到start()

或实现ApplicationListener<ConstextRefreshedEvent>并在获取事件时执行发送。

两种方法都可以确保应用程序已准备就绪。

刚发现问题。 实际上, MessageSender.onConstruct需要花费大量时间(100秒)来执行,在此期间,它阻止了Spring创建其他bean。

暂无
暂无

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

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