java - 无法从容器外部运行的 Spring Boot 应用程序连接到容器中运行的 Kafka

标签 java docker spring-boot apache-kafka spring-kafka

<分区>

我通过以下方式在本地运行 kafka:

docker-compose.yml

  zookeeper:
    image: 'bitnami/zookeeper:latest'
    ports:
      - 2181:2181
    environment:
      - ALLOW_ANONYMOUS_LOGIN=yes
  kafka:
    image: 'bitnami/kafka:latest'
    ports:
      - 9092:9092
    environment:
      - KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181
      - ALLOW_PLAINTEXT_LISTENER=yes
      - KAFKA_ADVERTISED_PORT=9092
      - KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://localhost:9092

我的 Spring Boot 应用程序运行在:

应用程序.yml:

spring:
  application:
    name: testkafka
  kafka:
    bootstrap-servers: localhost:9092

server:
  port: 8080

当我运行它并尝试发送到 kafka 上的主题时,我得到:

org.springframework.kafka.KafkaException: Reply timed out
    at org.springframework.kafka.requestreply.ReplyingKafkaTemplate.lambda$sendAndReceive$0(ReplyingKafkaTemplate.java:196) ~[spring-kafka-2.1.10.RELEASE.jar:2.1.10.RELEASE]
    at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-5.0.10.RELEASE.jar:5.0.10.RELEASE]
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) ~[na:na]
    at java.base/java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:264) ~[na:na]
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java) ~[na:na]
    at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) ~[na:na]
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
    at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]

如果我从 docker 容器内部运行 spring boot(使用一个 docker compose 文件),那么它工作:

在同一个 Compose 中运行:

version: "3.0"
services:
  service1:
    build: ./Service
    ports:
      - 8080:8080
      - 5005:5005
    links:
      - zookeeper
      - kafka
  zookeeper:
    image: 'bitnami/zookeeper:latest'
    ports:
      - 2181:2181
    environment:
      - ALLOW_ANONYMOUS_LOGIN=yes
  kafka:
    image: 'bitnami/kafka:latest'
    ports:
      - 9092:9092
    environment:
      - KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181
      - ALLOW_PLAINTEXT_LISTENER=yes
      - KAFKA_ADVERTISED_PORT=9092
      - KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://localhost:9092

如何让 kafka 容器允许来自自身/docker 外部的连接?

编辑:尝试了这些更改:

kafka:
  image: 'bitnami/kafka:latest'
  ports:
    - 9092:9092
  environment:
    - KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181
    - ALLOW_PLAINTEXT_LISTENER=yes
    - KAFKA_ADVERTISED_PORT=9092
    - KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://kafka:9092

和:

spring:
  application:
    name: testkafka
  kafka:
    bootstrap-servers: kafka:9092

server:
  port: 8080

这仍然超时

最佳答案

If I run the spring boot from inside a docker container (using one docker compose file), then it does work

实际上,它不应该起作用。 Kafka 不作为应用程序的一部分运行,因此本部分不指向 Kafka 容器。

kafka:
    bootstrap-servers: localhost:9092

它需要是 Docker 网络中的 kafka:9092

and ... bootstrap-servers: kafka:9092 ... still times out

那是因为你还有 KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://localhost:9092


在 Docker 网络内部和外部,通过指定 KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://localhost:9092,您表示您的客户端接收 Kafka Bootstrap 连接作为 localhost:9092,这将在 Docker 网络之外工作,只是因为您已经进行了端口转发并且您的容器在 localhost 上运行,但是,在 Docker 网络内部,如前所述,localhost 意味着 that应用程序容器,而不是代理。

解决方案是通过该属性创建两个端口映射,正如 this blog post 详细讨论的那样

另外,Confluent provides a fully configured Docker Compose具有适用于 Docker 内外的适当映射

    ports:
      - "9092:9092"
      - "29092:29092"
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_ZOOKEEPER_CONNECT: 'zookeeper:2181'
      ALLOW_PLAINTEXT_LISTENER: "yes"
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
      KAFKA_LISTENERS: PLAINTEXT://:9092,PLAINTEXT_HOST://0.0.0.0:29092
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:29092

对于Docker网络内的应用,使用kafka:9092,对于外部的应用,使用localhost:29092

编辑 bitnami 配置变量已更改。请参阅自述文件的这一部分

https://github.com/bitnami/bitnami-docker-kafka/blob/master/README.md#accessing-kafka-with-internal-and-external-clients

关于java - 无法从容器外部运行的 Spring Boot 应用程序连接到容器中运行的 Kafka,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53089486/

相关文章:

java - 扩展List增加字段是否合适

java - MediaPlayer 使我的应用程序崩溃(编辑 : it was caused by an out of bound array)

docker - 使用 docker compose 为不同的 IP 地址缩放容器

Docker 无法解析私有(private)网络上的 DNS

java - 处理程序调度失败;嵌套异常是具有根本原因的 java.lang.StackOverflowError

java - 这是否可以使用 Selenium 和 Java 来自动化 Angular Web 应用程序?

java - 如何将class文件制作成JAR文件

docker - Gradle构建失败

java - 如何在 Spring Boot 应用程序中读取我的 META-INF/MANIFEST.MF 文件?

spring-boot - 升级到 Spring Boot 3.10 后无法初始化使用 @Repository 注解的类