我正在使用wurstmeister's docker-kafka项目在容器中运行kafka / zookeeper。我使用localhost作为KAFKA_ADVERTISED_HOST_NAME: localhost
变量,对Docker组成了容器。
我编写了一个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程序无法与正在运行的Kafka服务器进行通信有关在另一个容器中。
这是我的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构建,docker在我的Java应用程序的映像上运行。没什么。
我被困住了。我在做什么错了?
答案 0 :(得分:2)
您需要正确设置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实际问题的黑客。
答案 1 :(得分:1)
KAFKA_ADVERTISED_HOST_NAME: localhost
是您的客户端将收到的与Kafka的连接字符串。这意味着带有您的应用程序的容器将尝试到达localhost的Kafka,其中localhost是带有您的应用程序的容器的本地网络堆栈。
要解决该问题,您应该使用kafka
主机作为您的KAFKA_ADVERTISED_HOST_NAME和引导服务器-这将允许您的容器在docker内部连接到kafka,但是当您尝试通过在PC上运行来连接到Kafka时会破坏配置java -jar ...
要解决该问题,请使用映射kafka-> localhost在PC上的主机文件中输入。