与位于docker主机外部的kafka docker容器进行交互

21
我已经构建了一个 Kafka 的 Docker 容器,并使用 docker-compose 进行编排。
运行 docker ps 命令后,我得到如下输出:
CONTAINER ID        IMAGE                          COMMAND                CREATED             STATUS              PORTS                                         NAMES
    5bde6f76246e        hieutrtr/docker-kafka:0.0.1    "/start.sh"            About an hour ago   Up About an hour    7203/tcp, 0.0.0.0:32884->9092/tcp             dockerkafka_kafka_3
    be354f1b8cc0        hieutrtr/docker-ubuntu:devel   "/usr/bin/supervisor   About an hour ago   Up About an hour    22/tcp                                        producer1
    50d3203af90e        hieutrtr/docker-kafka:0.0.1    "/start.sh"            About an hour ago   Up About an hour    7203/tcp, 0.0.0.0:32883->9092/tcp             dockerkafka_kafka_2
    61b285f39615        hieutrtr/docker-kafka:0.0.1    "/start.sh"            2 hours ago         Up 2 hours          7203/tcp, 0.0.0.0:32882->9092/tcp             dockerkafka_kafka_1
    20c9c5ccec05        jplock/zookeeper:3.4.6         "/opt/zookeeper/bin/   2 hours ago         Up 2 hours          2888/tcp, 3888/tcp, 0.0.0.0:32881->2181/tcp   dockerkafka_zookeeper_1

我可以在Docker容器内部运行生产者和消费者,但是在Docker网络之外无法工作。

例如:

我在本地主机上运行Kafka生产者,出现以下错误:

$ kafka_2.9.1-0.8.2.1: bin/kafka-console-producer.sh --topic test --broker-list $DOCKER_HOST:32884
[2015-08-31 06:55:15,450] WARN Property topic is not valid (kafka.utils.VerifiableProperties)
to
[2015-08-31 06:55:20,214] WARN Failed to send producer request with correlation id 2 to broker 1 with data for partitions [test,0] (kafka.producer.async.DefaultEventHandler)
java.nio.channels.ClosedChannelException
    at kafka.network.BlockingChannel.send(BlockingChannel.scala:100)
    at kafka.producer.SyncProducer.liftedTree1$1(SyncProducer.scala:73)
    at kafka.producer.SyncProducer.kafka$producer$SyncProducer$$doSend(SyncProducer.scala:72)
    at kafka.producer.SyncProducer$$anonfun$send$1$$anonfun$apply$mcV$sp$1.apply$mcV$sp(SyncProducer.scala:103)
    at kafka.producer.SyncProducer$$anonfun$send$1$$anonfun$apply$mcV$sp$1.apply(SyncProducer.scala:103)
    at kafka.producer.SyncProducer$$anonfun$send$1$$anonfun$apply$mcV$sp$1.apply(SyncProducer.scala:103)
这是我在Github上的Kafka Docker示例,其中包含所提到的问题。
那么,是否有人遇到相同的问题并可以以任何方式帮助我呢? 附加信息: (只是从ches / kafka中分叉并对docker-compose进行修改):
5个回答

10
在Kafka服务器属性中,您需要将advertised.listeners设置为正在运行容器的IP/端口,然后它应该可以工作。

2
我认为这不是问题所在。因为我仍然可以从我的本地主机创建主题。这与java.rmi有关吗? - Trung Hiếu Trần
3
这是我针对非常相似的症状所做出的解决方案。我可以从本地主机或其他容器创建主题,但在设置了“advertised.host.name”之前无法发布任何消息。 - Lundahl
1
我们应该将什么作为advertised.host.name?我也遇到了同样的问题。 - Siddharth Gupta
advertised.host.name现已弃用,我不得不使用advertised.listener。 - Ashwin Chandran

7

以下是我的两分意见,因为我曾经很难搞清楚这个问题。

我的$KAFKA_HOME/config/server.properties 包含以下内容:

listener.security.protocol.map=INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT

advertised.listeners=INSIDE://${container_ip}:9092,OUTSIDE://${outside_host_ip}:29092

listeners=INSIDE://:9092,OUTSIDE://:29092

inter.broker.listener.name=INSIDE

这会创建两个连接,一个用于Docker内部,另一个用于外部使用。您必须为后者选择一个新端口,在我的例子中是29092,确保此端口在Docker中公开并映射。

我还无法找到没有${outside_host_ip}环境变量的解决方案,因此我将主机机器的IP地址作为环境变量提供。

测试:

  1. 进入Kafka容器并创建主题:./kafka-topics.sh -zookeeper zookeeper:2181 --create --topic dummytopic --partitions 1 --replication-factor 1
  2. 从Kafka容器外部执行:./kafka-console-producer.sh --broker-list 0.0.0.0:29092 --topic dummytopic 并输入一条消息

希望这对其他人有所帮助。


注意到内部和外部的端口必须不同。我不明白为什么会这样。有人知道为什么当这些端口相同时,Kafka会抛出异常吗?你可能会认为Docker网络内部的端口可以随意设置,而不会对Docker网络外部的端口产生任何影响。如果端口相同,Kafka会从某个Java参数解析器中抛出异常。 - undefined

3
您需要提供部署docker实例的主机名称。同时,您还需要将docker主机机器(public)的端口映射到docker容器实例(private)中。

请确保您不在server.properties中设置任何相关属性。 - sivakadi
抱歉,我按下回车键太早了。 - sivakadi
# The id of the broker. This must be set to a unique integer for each broker. broker.id=0 #listeners=PLAINTEXT://localhost:9092 #advertised.listeners=PLAINTEXT://localhost:9092 #advertised.host.name=localhost #advertised.port=9092 - sivakadi
请原谅我第一次使用。在server.properties中设置的值优先级最高,根据我的经验,默认情况下端口为9092。我在同一个Kafka中运行开发和QA Docker Kafka。没有在任何地方设置端口,但是使用docker容器的公开端口作为9092。将这些端口映射到公共/ docker主机端口分别为9092和9192的dev和qa。 - sivakadi

0

记录一下,另一种让我的本地kafka消费者与Docker容器内的远程broker通信的方法是在我的/etc/hosts中添加一个条目:docker-host-ip-address docker-kafka-container-hostname

无论如何,Lundahl的解决方案对我来说都很好用,而且似乎更加干净。更干净的方法是设置advertised.listeners=host-ip:port,因为advertised.host.nameadvertised.port已经被弃用。


0

简而言之 在主机上公开端口9092并将其映射到容器端口9092,以便在容器外访问kafka代理。有关详细信息,请参见docker-compose文档。

我认为问题在于您没有在容器外部公开9092端口。根据您的docker ps列表,您的9092容器端口动态映射到主机的端口范围32882-32884。 当您连接到配置为此方式的代理时,您会收到包含广告端口9092的元数据。使用此元数据,生产者尝试通过端口9092进行其他请求并失败。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接