在当今的软件开发领域,容器化技术成为了一种越来越流行的部署方式。而Docker作为最受欢迎的容器化解决方案之一,为开发者提供了便捷的环境隔离和部署方式。对于使用Kafka作为消息队列系统的开发者来说,将Kafka与Docker结合起来,可以更加灵活和高效地进行开发和部署。在本篇文章中,php小编西瓜将为大家介绍如何在Docker中运行Kafka,让您轻松享受容器化带来的便利。
我在本地计算机上设置了一个单节点 kafka docker 容器,如 confluence 文档中所述(步骤 2-3)。
此外,我还公开了 zookeeper 的端口 2181 和 kafka 的端口 9092,以便我能够从本地计算机上运行的客户端连接到它们:
$ docker run -d \ -p 2181:2181 \ --net=confluent \ --name=zookeeper \ -e zookeeper_client_port=2181 \ confluentinc/cp-zookeeper:4.1.0 $ docker run -d \ --net=confluent \ --name=kafka \ -p 9092:9092 \ -e kafka_zookeeper_connect=zookeeper:2181 \ -e kafka_advertised_listeners=plaintext://kafka:9092 \ -e kafka_offsets_topic_replication_factor=1 \ confluentinc/cp-kafka:4.1.0
问题:当我尝试从主机连接到 kafka 时,连接失败,因为 无法解析地址:kafka:9092
。
这是我的 java 代码:
properties props = new properties(); props.put("bootstrap.servers", "localhost:9092"); props.put("client.id", "kafkaexampleproducer"); props.put("key.serializer", longserializer.class.getname()); props.put("value.serializer", stringserializer.class.getname()); kafkaproducer<long, string> producer = new kafkaproducer<>(props); producerrecord<long, string> record = new producerrecord<>("foo", 1l, "test 1"); producer.send(record).get(); producer.flush();
例外:
java.io.IOException: Can't resolve address: kafka:9092 at org.apache.kafka.common.network.Selector.doConnect(Selector.java:235) ~[kafka-clients-2.0.0.jar:na] at org.apache.kafka.common.network.Selector.connect(Selector.java:214) ~[kafka-clients-2.0.0.jar:na] at org.apache.kafka.clients.NetworkClient.initiateConnect(NetworkClient.java:864) [kafka-clients-2.0.0.jar:na] at org.apache.kafka.clients.NetworkClient.ready(NetworkClient.java:265) [kafka-clients-2.0.0.jar:na] at org.apache.kafka.clients.producer.internals.Sender.sendProducerData(Sender.java:266) [kafka-clients-2.0.0.jar:na] at org.apache.kafka.clients.producer.internals.Sender.run(Sender.java:238) [kafka-clients-2.0.0.jar:na] at org.apache.kafka.clients.producer.internals.Sender.run(Sender.java:176) [kafka-clients-2.0.0.jar:na] at java.lang.Thread.run(Thread.java:748) [na:1.8.0_144] Caused by: java.nio.channels.UnresolvedAddressException: null at sun.nio.ch.Net.checkAddress(Net.java:101) ~[na:1.8.0_144] at sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:622) ~[na:1.8.0_144] at org.apache.kafka.common.network.Selector.doConnect(Selector.java:233) ~[kafka-clients-2.0.0.jar:na] ... 7 common frames omitted
问题:如何连接到在 docker 中运行的 kafka?我的代码是从主机运行的,而不是 docker。
注意:我知道理论上我可以尝试 dns 设置和 /etc/hosts
但这是一种解决方法 - 不应该是这样的。
这里也有类似的问题,但它是基于 ches/kafka
图像。我使用基于 confluenceinc
的图像,这是不一样的。ches/kafka
图像。我使用基于 confluenceinc
的图像,这是不一样的。
tl;dr - 从容器到主机的简单端口转发将不起作用...主机文件(例如 *NIX 系统上的 /etc/hosts
advertished.listeners
(不是 advertished.host.name
和 advertished.port
,因为这些已被弃用)。如果您看到诸如 Connection to node -1 (localhost/127.0.0.1:9092)
- 从容器到主机的简单端口转发将bootstrap.servers
一部分列出的服务器实际上是可解析的。例如 ping
IP/主机名,使用 netcat
检查端口...如果您的客户端位于容器中,则需要从容器执行此操作,而不是(仅)从主机执行此操作。如果容器没有立即崩溃以访问其 shell,请使用 docker exec
不起作用
)不应修改以解决 Kafka 网络问题,因为此解决方案不可移植。docker ps
显示 kafka 容器是从 0.0.0.0 映射的:<host_port> -> <advertished_listener_port> /tcp
之类的错误,则意味着您的应用程序容器尝试连接到自身。您的应用程序容器是否也在运行 Kafka 代理进程?可能不是。confluenceinc
docker 镜像来解决所提出的问题,不是 wurstmeister/kafka
。如果您设置了 KAFKA_ADVERTISED_HOST_NAME
。
3) 如果从主机而不是另一个容器运行进程,要验证端口是否在主机上正确映射,请确保 .如果尝试从 Docker 网络外部运行客户端,则端口必须匹配。两个容器之间不需要端口转发;使用链接/docker网络
下面的答案使用 confluenceinc
docker 镜像来解决所提出的问题,不是 。如果您设置了 KAFKA_ADVERTISED_HOST_NAME
变量,请将其删除(这是一个已弃用的属性)
wurstmeister/kafka
Apache。
您只依赖于它的配置方式。以及 a>哪些变量导致了这种情况。
bitnami/kafka
wurstmeister
请参阅有关监听器配置的自述文件部分,另外
debezium/kafka
如果您想要一个小容器,请尝试这些。这些图像比 Confluence 小得多,并且比
维护得更好。 🎜参考他们的监听器配置的自述文件🎜。🎜 🎜🎜🎜 🎜此处提到了相关文档🎜此处🎜。🎜注意:已弃用公布的主机和端口设置。广告听众涵盖了两者。与 Confluence 容器类似,Debezium 可以使用 KAFKA_
前缀的代理设置来更新其属性。
ubuntu/kafka
要求您通过 Docker 映像参数添加 --overrideadvertising.listeners=kafka:9092
...我发现它不如环境变量可移植,因此不推荐spotify/kafka
已弃用且已过时。fast-data-dev
或 lensesio/box
非常适合一体化解决方案,具有架构注册表、Kafka Connect 等,但如果您仅想要 Kafka,则显得臃肿。另外,这是一种在一个容器中运行多个服务的 Docker 反模式Dockerfile
- 为什么?这些其他的东西是否不完整?从拉取请求开始,而不是从头开始。有关补充阅读、功能齐全 docker-compose
和网络图,请参阅 此博客作者:@rmoff
Confluence 快速入门 (Docker) 文档 假定所有生产和消费请求将在 Docker 网络内进行。
您可以通过在自己的容器中运行 Kafka 客户端代码(使用 Docker 网桥)来解决连接到 kafka:9092
的问题,但否则您需要添加更多环境变量以将容器公开到外部,同时仍然让它在 Docker 网络中工作。
首先添加 PLAINTEXT_HOST:PLAINTEXT
的协议映射,它将侦听器协议映射到 Kafka 协议
密钥:KAFKA_LISTENER_SECURITY_PROTOCOL_MAP
值: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
然后在不同的端口上设置两个通告的侦听器。 (这里的 kafka
指的是 docker 容器名称;它也可能被命名为 broker
,因此请仔细检查您的服务 + 主机名)。
键:KAFKA_ADVERTISED_LISTENERS
值:PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:29092
请注意,此处的协议与上面协议映射设置的左侧值相匹配
运行容器时,添加 -p 29092:29092
进行主机端口映射,并通告 PLAINTEXT_HOST
监听器。
所以...(使用上述设置)
如果仍然不起作用,可以将 KAFKA_LISTENERS
设置为包含 <PROTOCOL>://0.0.0.0:<PORT>
,其中两个选项都与广告设置和 Docker 转发的端口匹配
广告本地主机和关联的端口将允许您在容器外部进行连接,正如您所期望的那样。
换句话说,当在 Docker 网络之外运行任何 Kafka 客户端(包括您可能在本地安装的 CLI 工具)时,请使用 localhost:29092
作为引导服务器,使用 localhost:2181
作为 Zookeeper(需要 Docker)端口转发)
如果尝试从外部服务器连接,您需要公布主机的外部主机名/IP(例如 192.168.x.y
)以及/代替 localhost 。
简单地通过端口转发来通告 localhost 是行不通的,因为 Kafka 协议仍将继续通告您配置的侦听器。
如果不在同一个本地网络中,此设置需要 Docker 端口转发和路由器端口转发(以及防火墙/安全组更改),例如,您的容器在云中运行,并且您想要从本地计算机与其交互。
这是最不容易出错的配置;您可以直接使用 DNS 服务名称。
在 Docker 网络中运行应用程序时,使用 kafka:9092
(请参阅上面广告的 PLAINTEXT
侦听器配置)作为引导服务器,使用 zookeeper:2181
(请参阅上面广告的 PLAINTEXT
侦听器配置)作为引导服务器,使用 zookeeper:2181
作为 Zookeeper,就像任何其他 Docker 服务通信一样(不不需要任何端口转发)
如果您使用单独的 docker run
命令或 Compose 文件,则需要使用 compose networks
部分或 docker network --create
手动定义共享 network
参见完整 Confluence 堆栈的示例 Compose 文件 或 针对单个经纪商的更简单的。
如果使用多个代理,那么它们需要使用唯一的主机名+广告侦听器。 查看示例一个>
从 Docker (ksqlDB) 连接到主机上的 Kafka
对于任何对 Kubernetes 部署感兴趣的人:
以上是连接到在 Docker 中运行的 Kafka的详细内容。更多信息请关注PHP中文网其他相关文章!