Spring Boot 应用程序无法在 Docker 中将事件发布到 Kafka

Posted

技术标签:

【中文标题】Spring Boot 应用程序无法在 Docker 中将事件发布到 Kafka【英文标题】:Spring Boot app is not able to publish events to Kafka in Docker 【发布时间】:2022-01-05 05:30:55 【问题描述】:

各位程序员大家好!

我正在学习 Docker 和 Kafka,如果有任何帮助,我将不胜感激。问题是应用程序能够连接到 Kafka,但不能发布任何事件。错误:

org.apache.kafka.common.errors.TimeoutException: Expiring 2 record(s) for wages-local-0:120001 ms has passed since batch creation

当一个 Docker 容器中的 Spring Boot 应用程序尝试发布到另一个容器中的 Kafka 时,会出现此问题:

version: '3'

services:
  zookeeper:
    image: wurstmeister/zookeeper
    container_name: zookeeper
    ports:
      - "2181:2181"
  kafka:
    image: wurstmeister/kafka
    container_name: kafka
    hostname: kafka
    ports:
      - "9092:9092"
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_ADVERTISED_PORT: 9092
      KAFKA_ADVERTISED_HOST_NAME: kafka
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_LISTENERS: INTERNAL://kafka:9092
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT
      KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
    depends_on:
      - zookeeper
  publisher_app:
    build:
      context: ./kafka-publisher
    ports:
      - 8080:8080
    depends_on:
      - "kafka"
    environment:
      kafka.wages-topic.bootstrap-address: kafka:9092
    links:
      - kafka:kafka

这里是源代码链接:https://github.com/aleksei17/springboot-rest-kafka-mysql/blob/master/docker-compose.yml

【问题讨论】:

你能从你的主机ping到那个容器吗?这似乎是 docker 容器中的网络问题。按照以下链接获取解决方案:- ***.com/questions/24319662/… kafka.wages-topic.bootstrap-address 看起来不像环境变量 这是一个来自 application.yml 的变量,在这里使用它:github.com/aleksei17/springboot-rest-kafka-mysql/blob/master/… 【参考方案1】:

好吧,看来我需要在使用后删除容器。当我这样做时,在启动 Kafka 容器时出现错误,例如:unknown listener PLAINTEXT。所以我将 PLAINTEXT 更改为 INTERNAL,它起作用了!这是 Kafka 的 docker-compose 的最终版本:

  kafka:
    image: wurstmeister/kafka
    container_name: kafka
    hostname: kafka
    ports:
      - "9092:9092"
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_ADVERTISED_PORT: 9092
      KAFKA_ADVERTISED_HOST_NAME: kafka
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_LISTENERS: INTERNAL://kafka:9092
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT
      KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
    depends_on:
      - zookeeper

如果它既适用于 Dockerized 应用程序,也适用于在 Docker 之外的同一主机上运行的应用程序,那就太好了,但这是另一回事。玩过这个教程,但到目前为止没有成功:https://www.baeldung.com/kafka-docker-connection

【讨论】:

你只有一个监听器和一个broker,PLAINTEXT是内置的,所以你不需要映射或者inter-broker监听器【参考方案2】:

您的配置被硬编码为使用localhost:9092

您想像这样 externalize the config (删除您的 kafka.wages-topic 部分,因为引导服务器不是特定于主题的设置)

spring:
  kafka:
    bootstrap-servers: $BOOTSTRAP_SERVERS

然后在 Compose 中,

environment:
  BOOTSTRAP_SERVERS: kafka:9092

要配置主题,请参阅https://docs.spring.io/spring-kafka/reference/html/#configuring-topics

【讨论】:

感谢您的回答! localhost:9092 似乎没有问题,因为这在 docker-compose 中被 kafka.wages-topic.bootstrap-address 覆盖。我宁愿离开 application.yml 以便从 IntelliJ 运行更容易 您可以将环境变量添加到 IntelliJ Run Configurations 以使其在两种情况下都能正常工作

以上是关于Spring Boot 应用程序无法在 Docker 中将事件发布到 Kafka的主要内容,如果未能解决你的问题,请参考以下文章