Spring Kafka单元测试侦听器未订阅主题

时间:2020-03-10 06:09:36

标签: spring spring-boot apache-kafka spring-kafka spring-kafka-test

我有一个示例项目,用kafka探索春天(找到here)。我有一个听者订阅主题 my-test-topic-stream ,该主题只是查找消息和密钥,并将其发布到另一个主题 my-test-topic-downstream 。我试过这是本地的kafka( docker-compose 文件在那里)并且可以工作。

现在,我正在尝试使用嵌入式kafka服务器为此编写测试。在测试下,我有一个嵌入式服务器正在启动( TestContext.java ),该服务器应在测试之前启动(被覆盖的junit beforeAll )。

private static EmbeddedKafkaBroker kafka() {
    EmbeddedKafkaBroker kafkaEmbedded =
        new EmbeddedKafkaBroker(
            3,
            false,
            1,
            "my-test-topic-upstream", "my-test-topic-downstream");
    Map<String, String> brokerProperties = new HashMap<>();
    brokerProperties.put("default.replication.factor", "1");
    brokerProperties.put("offsets.topic.replication.factor", "1");
    brokerProperties.put("group.initial.rebalance.delay.ms", "3000");
    kafkaEmbedded.brokerProperties(brokerProperties);
    try {
      kafkaEmbedded.afterPropertiesSet();
    } catch (Exception e) {
      throw new RuntimeException(e);
    }

    return kafkaEmbedded;
  }

然后,我创建一个生产者( TickProducer )并将消息发布到该主题,我希望我的听众可以使用该消息。

public TickProducer(String brokers) {
    Properties props = new Properties();
    props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, brokers);
    props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
    props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());

    producer = new KafkaProducer<>(props);
  }

  public RecordMetadata publishTick(String brand)
          throws ExecutionException, InterruptedException {
    return publish(TOPIC, brand, Instant.now().toString());
  }

  private RecordMetadata publish(String topic, String key, String value)
      throws ExecutionException, InterruptedException {
    final RecordMetadata recordMetadata;
    recordMetadata = producer.send(new ProducerRecord<>(topic, key, value)).get();
    producer.flush();
    return recordMetadata;
  }

我看到以下日志消息继续记录。

11:32:35.745 [main] WARN  o.apache.kafka.clients.NetworkClient - [Consumer clientId=consumer-1, groupId=my-test-group] Connection to node -1 could not be established. Broker may not be available.

最终失败

11:36:52.774 [main] ERROR o.s.boot.SpringApplication - Application run failed
org.springframework.context.ApplicationContextException: Failed to start bean 'org.springframework.kafka.config.internalKafkaListenerEndpointRegistry'; nested exception is org.apache.kafka.common.errors.TimeoutException: Timeout expired while fetching topic metadata

这里有提示吗?

1 个答案:

答案 0 :(得分:1)

查看INFO日志ConsumerConfig,以查看他尝试连接的位置(将其与ProducerConfig进行比较)。我怀疑您尚未更新Spring Boot bootstrap-servers属性以指向嵌入式代理。

请参见

/**
 * Set the system property with this name to the list of broker addresses.
 * @param brokerListProperty the brokerListProperty to set
 * @return this broker.
 * @since 2.3
 */
public EmbeddedKafkaBroker brokerListProperty(String brokerListProperty) {
    this.brokerListProperty = brokerListProperty;
    return this;
}

将其设置为spring.kafka.bootstrap-servers,它将代替SPRING_EMBEDDED_KAFKA_BROKERS使用。

顺便说一句,通常使用@EmbeddedKafka注释比自己实例化服务器更容易。