【问题标题】:Docker / Kafka connect two different containersDocker / Kafka 连接两个不同的容器
【发布时间】:2019-10-27 18:47:59
【问题描述】:

我正在使用wurstmeister's docker-kafka 项目在容器中运行 kafka/zookeeper。我使用 localhost 作为KAFKA_ADVERTISED_HOST_NAME: localhost 变量来构建容器。

我编写了一个 Java 应用程序,它使用 flink 来连接和消费这个 Kafka 容器的一个主题。如果我导出一个可运行的 jar 并从我的机器上运行它,它绝对可以正常工作。当我创建以下图像以从另一个 docker 容器运行 jar 时,我收到一个异常(执行后大约 30 秒)Exception in thread "main" org.apache.flink.runtime.client.JobExecutionException: org.apache.kafka.common.errors.TimeoutException: Timeout expired while fetching topic metadata,我认为这与我的 Java 程序无法与运行在其他容器。

这是我的 Java 应用程序的 dockerfile:

# Dockerfile

FROM anapsix/alpine-java

MAINTAINER myself myself

COPY myApp.jar /home/myApp.jar

CMD ["java","-jar","/home/myApp.jar"]

这是 wurstmeister 的 docker kafka 的 docker-compose.yml:

version: "3.5"

networks:
  myNetwork:
    name: myNetwork
    driver: bridge

services:
  zookeeper:
    image: wurstmeister/zookeeper
    ports:
      - "2181:2181"
    networks:
      - myNetwork
  kafka:
    build: .
    ports:
      - "9092:9092"
    environment:
      KAFKA_ADVERTISED_HOST_NAME: localhost
      KAFKA_ADVERTISED_PORT: "9092"
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true"
      ALLOW_PLAINTEXT_LISTENER: "yes"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - myNetwork
  auth_analytics:
      build: 
        context: .
        dockerfile: auth_dockerfile
      depends_on:
        - kafka
      networks:
        - myNetwork

我已经尝试了上述的多个版本。最初我没有设置任何我认为可能是问题的网络,但是,以上创建网络并没有任何区别。我在我的 Java 应用程序中尝试了“localhost:9092”作为引导服务器,并在网上阅读时尝试了“myNetwork:9092”。

我还从 wurstmeister 阅读了这篇关于连接性的 FAQ,但我认为我的设置没有问题。

我还尝试在不使用 docker-compose 的情况下运行我的 Java 应用程序映像(我运行了 docker-compose 来启动 zookeeper/kafka,然后我做了一个 docker build,docker run 在我的 Java 应用程序的映像上运行。这个没有区别。)

我被困住了。我做错了什么?

【问题讨论】:

    标签: docker apache-kafka docker-compose


    【解决方案1】:

    您需要正确设置KAFKA_ADVERTISED_LISTENERS。目前它是localhost,这意味着代理将告知任何连接的客户端该代理在localhost 上——当客户端尝试连接时,它将失败(除非 Kafka 代理实际上在localhost,它不会在仅运行您的应用程序的 Docker 容器上)。

    解决方案是定义侦听器,以便可以从需要它的任何代理和客户端位置对其进行寻址。我的首选方法是this,其中一种用于容器内通信,另一种用于从主机进行通信:

      KAFKA_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
      KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092
    

    您在 Docker 网络上的客户端使用kafka:29092 进行连接;主机上的客户端连接到 localhost:9092(并确保通过 Docker 将 9092 暴露给主机)。

    要了解更多信息,请参阅https://rmoff.net/2018/08/02/kafka-listeners-explained/

    顺便说一句,我强烈建议以正确的方式解决此问题;覆盖/etc/hosts 文件是一种无法解决IMO 实际问题的hack。

    【讨论】:

    • 这很有帮助,但是当我将这 3 行添加到我的 docker-compose 时,我得到一个“java.lang.IllegalArgumentException:要求失败:adverted.listeners 侦听器名称必须等于或子集在侦听器中定义的那些。找到 PLAINTEXT,PLAINTEXT_HOST。基于当前配置的有效选项是来自 kafka 的 PLAINTEXT" 异常。
    • 您可能还需要指定KAFKA_LISTENERS,我已经更新了我的答案。请注意,我提供的配置是一个示例,并且使用的是 Confluent docker 图像。如果您想从中复制完整示例,请参阅this Docker Compose
    • 是的,我发现我需要我添加的 KAFKA_LISTENERS 并且 kafka 没有抛出异常,但是,我的客户端仍然拒绝连接。只是为了确保我没有做一些非常愚蠢的事情:这就是我需要为我的客户端配置提供的内容: bootstrap.servers=kafka:29092 zookeeper.connect=zookeeper:2181 。正确的?我实际上检查了完整的代码并根据该代码设置了我的项目,但我的应用程序仍然失败......
    • 是的,如果您的应用程序在与代理相同的 docker 网络上的容器上运行,那么 kafka:29092 应该可以工作。
    • 我不得不将 KAFKA_LISTENERS 更改为 KAFKA_LISTENERS: PLAINTEXT://:29092,PLAINTEXT_HOST://:9092,现在它可以工作了。另一个问题是我的 Java 应用程序必须在 Kafka 完全初始化后启动。因此,当 zookeeper/kafka 成功启动时,我在新的 docker-compose 中按需启动。
    【解决方案2】:

    KAFKA_ADVERTISED_HOST_NAME: localhost

    是您的客户端将作为连接字符串接收到 Kafka 的内容。这意味着您的应用程序的容器将尝试在 localhost 访问 Kafka,其中 localhost 是您的应用程序容器的本地网络堆栈。

    要解决这个问题,您应该使用 kafka 主机作为您的 KAFKA_ADVERTISED_HOST_NAME 和引导服务器 - 这将允许您的容器连接到 docker 内的 kafka,但是当您尝试通过在 PC 上运行 java 连接到 Kafka 时会中断配置 -罐子...

    要解决这个问题,请使用映射 kafka -> localhost 在 PC 上的主机文件中输入条目。

    【讨论】:

    • 我已将 KAFKA_ADVERTISED_HOST_NAME 更改为 kafka。我将我的应用程序配置更改为 kafka:9092、kafka.myNetwork:9092 并将我的 zookeeper 更改为 zookeeper:2181、zookeeper.myNetwork:2181(所有可能的组合),但我没有运气。您能否告诉我哪个应该是主机:引导服务器和 Zookeeper 在我的客户端中连接的 IP?
    猜你喜欢
    • 2020-01-06
    • 1970-01-01
    • 2018-03-01
    • 1970-01-01
    • 2021-11-24
    • 2021-01-26
    • 2018-06-16
    • 2020-01-30
    • 1970-01-01
    相关资源
    最近更新 更多