无法在Spring Boot中使用Kafka消息

时间:2018-02-07 15:10:33

标签: spring-boot apache-kafka kafka-consumer-api spring-kafka

我们有一个使用org.apache.kafka.clients.consumer.KafkaConsumer

消耗Kafka消息的Java应用程序

我们已经创建了一个具有Spring-Kafka依赖关系的Spring Boot应用程序,但是无法读取新项目中的消息。已经检查了明显的参数,包括引导服务器的主机名和端口(日志显示被识别),组,主题和Spring Boot,就像原始使用者一样,使用StringDeserializer。这是我们的配置文件:

spring:
  kafka:
    bootstrap-servers: hostname1:9092,hostname2:9092
    consumer:
      auto-offset-reset: earliest
      group-id: our_group
      enable-auto-commit: false
      fetch-max-wait: 500
      max-poll-records: 1

kafka:
  topic:
    boot: topic.name 

和接收者:

@Component
public class Receiver {

    private static final Logger LOGGER = LoggerFactory.getLogger(Receiver.class);

    private CountDownLatch latch = new CountDownLatch(1);

    public CountDownLatch getLatch() {
        return latch;
    }

    @KafkaListener(topics = "${kafka.topic.boot}")
    public void receive(ConsumerRecord<?, ?> consumerRecord) {
        LOGGER.info("received payload='{}'", consumerRecord.toString());
        latch.countDown();
    }

}

以下是启动Boot应用程序的代码:

@SpringBootApplication
public class EmsDemoUsingSpringBootApplication {

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

此异常被捕获:

org.apache.kafka.common.errors.TimeoutException: Failed to update metadata after 60000 ms.

有什么明显我忽略了吗? 调试它的最佳方法是什么?

由于

2 个答案:

答案 0 :(得分:1)

我希望您可能错过了需要在KafkaListenerContainerFactory文件中指定的@Configuration bean

@Bean
KafkaListenerContainerFactory<ConcurrentMessageListenerContainer<String, String>>
kafkaManualAckListenerContainerFactory() {
    ConcurrentKafkaListenerContainerFactory<String, String> factory =
            new ConcurrentKafkaListenerContainerFactory<>();
  factory.setConsumerFactory(new DefaultKafkaConsumerFactory<String, String>(new HashMap<String,Object>((Map)consumerConfig)));
  factory.setConcurrency(concurrentConsumerCount);
  factory.setBatchListener(true);
  return factory;
}

另外,对于消费者而言,请指定KafkaListenerContainerFactory

答案 1 :(得分:0)

我也遇到了这个问题,发生的事情是我无法连接到服务器。您可以在application.propertiesapplication.yml中更改日志级别以查看更多详细信息。恶魔在日志中。

logging:
  level:
    root: WARN
    org.springframework: INFO
    org.apache.kafka: DEBUG

有人告诉我Kafka无法处理名称查找,根据我的经验,要连接的主机几乎总是FQDN名称(包括域名和全部名称)。就我而言,我想我没有在虚拟框中设置域,也无法找到我的来宾框,即使我们在同一子网中也可以使用ping

此外,我为Kafka零件创建了另一个主类,结果是错误的。这不是一个好习惯,您应该使用@EnableKafka注释应用程序主类,然后将设置放入yml文件中,然后将其加载。不需要其他配置类。

我的消费者:

import lombok.extern.slf4j.Slf4j;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class KafkaConsumer {
    @KafkaListener(topics={"testtopic"})
    public void listen(@Payload String message) {
        log.info("Received message is {}", message);
    }
}

我的应用程序:

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.kafka.annotation.EnableKafka;

@Slf4j
@SpringBootApplication(exclude = { SecurityAutoConfiguration.class })
@EnableKafka    // <----- I only had to add this line
public class SomeApplication {

    public static void main(String[] args) {
        SpringApplication.run(SomeApplication.class, args);
        log.info("Application launched. ");
    }
}

我的配置yml:

logging:
  level:
    root: WARN
    org.springframework: INFO
    org.apache.kafka: DEBUG

spring:
  kafka:
    bootstrap-servers: <FQDN names here:9092>
    consumer:
      group-id: <unique-group-id>
      enable-auto-commit: false # never ack messsage when it is received.
    listener:
      ack-mode: manual # I am responsible to ack the messages

并启动该应用程序。就是这样。