kafka:从主机发布的事件不会被docker中运行的应用程序使用

lsmd5eda  于 2021-06-04  发布在  Kafka
关注(0)|答案(4)|浏览(318)

我正在为一个应用程序编写端到端测试。我启动一个应用程序的示例、一个kafka示例和一个zookeeper(都已停靠),然后与应用程序api交互以测试其功能。我需要在此应用程序中测试事件使用者的功能。我发布测试中的事件,应用程序将处理这些事件。
问题:如果我在本地(而不是docker)运行应用程序并运行将产生事件的测试,那么应用程序代码中的使用者将正确处理事件。在这种情况下,消费者和测试 bootstrapServers 设置为 localhost:9092 . 但如果应用程序作为停靠示例运行,则不会看到事件。在这种情况下 bootstrapServers 设置为 kafka:9092 在应用和 localhost:9092 在哪里考试 kafka 是docker容器名称。这个 kafka 容器暴露其 9092 端口到主机,以便可以从docker容器内部和主机(运行我的测试)访问相同的kafka示例。
代码中唯一的区别是 localhostkafka 设置为引导服务器。在这两种情况下,消费者和生产者都能成功启动;事件的发布没有错误。只是在一种情况下,消费者没有收到事件。
问题:如何让停靠的消费者看到从主机发布的事件?
注意:我有一个正确配置的docker网络,其中包括应用程序示例、zookeeper和kafka。他们都“看见”对方。的相应端口 kafka 以及 zookeeper 暴露于主机。Kafka港口: 0.0.0.0:9092->9092/tcp . zookeeper端口: 22/tcp, 2888/tcp, 3888/tcp, 0.0.0.0:2181->2181/tcp .
我正在使用wurstmeister/kafka和wurstmeister/zookeeper docker图像(我无法替换它们)。
如有任何想法,我们将不胜感激。你将如何调试它?
更新:问题是 KAFKA_ADVERTISED_LISTENERS 以及 KAFKA_LISTENERS 为内部和外部通信设置为不同端口的环境变量。解决方案是在docker容器中运行应用程序代码时,在应用程序代码中使用正确的端口。

eqzww0vc

eqzww0vc1#

你在停靠的应用程序中尝试过“host.docker.internal”吗?

7jmck4yq

7jmck4yq2#

这类问题通常与Kafka处理经纪人地址的方式有关。
当你开始一个Kafka经纪人,它绑定自己 0.0.0.0:9092 在zookeeper注册地址 <hostname>:9092 . 当您与客户机连接时,将联系zookeeper以获取特定代理的地址。
这意味着,当您启动Kafka容器时,您会遇到如下情况:
容器名称:Kafka
网络名称:kafkanet
主机名:Kafka
Zookeeper登记:kafka:9092
现在,如果您将客户机从kafkanet网络中的容器连接到您的kafka,那么从zookeeper获得的地址是 kafka:9092 可以通过 kafkanet 网络。
但是,如果您从docker外部连接到kafka(即使用 localhost:9092 端点由dockerMap),您仍然可以返回 kafka:9092 无法解析的地址。
为了解决这个问题,您可以指定 advertised.host.name 以及 advertised.port 在代理配置中,地址可由所有客户机解析(请参阅文档)。
通常的做法是 advertised.host.name 作为 <container-name>.<network> (在您的例子中类似于kafka.kafkanet)以便任何连接到网络的容器都能够正确解析kafka代理的ip。
然而,在您的例子中,您有一个混合的网络配置,因为一些组件位于docker内部(因此能够解析kafkanet网络),而其他组件则位于docker外部。如果是生产系统,我的建议是 advertised.host.name 到主机的dns/ip,始终依赖docker端口Map到达kafka代理。
然而,据我所知,你只需要这个设置来测试,所以最简单的事情就是“欺骗”docker之外的系统。使用上面指定的命名,这意味着只需将 /etc/hosts (或等同于windows的)行 127.0.0.1 kafka.kafkanet .
这样,当您住在docker外的客户连接到kafka时,应该会发生以下情况:
客户->Kafkavialocalhost:9092
Kafka询问Zookeeper并返回主人 kafka.kafkanet 客户端解析 kafka.kafkanet 至127.0.0.1
客户->Kafkavia 127.0.0.1:9092
编辑
正如在评论中指出的,Kafka的新版本现在使用了 listeners 以及 advertised.listeners 用来代替 host.name 以及 advertised.host.name (不推荐使用,仅在未指定上述选项的情况下使用)。但总体思路是一样的: host.name :指定kafka代理应将自身绑定到的主机(与一起工作)
port listeners :指定kafka代理应绑定到的所有端点(例如 PLAINTEXT://0.0.0.0:9092,SSL://0.0.0.0:9091 ) advertised.host.name :指定如何将代理播发给客户端(即客户端应使用哪个地址连接到它) avertised.listeners :指定所有播发端点(例如 PLAINTEXT://kafka.example.com:9092,SSL://kafka.example.com:9091 )
在这两种情况下,为了让客户能够成功地与Kafka沟通,他们需要能够解析并连接到 advertised 主机名和端口。
在这两种情况下,如果未指定它们,则由代理使用代理运行的计算机的主机名自动派生。

lnlaulya

lnlaulya3#

你一直在引用 8092 . 这是故意的吗?Kafka继续 9092 . 最简单的测试是下载相同版本的kafka并手动运行其 kafka-console-consumer 以及 kafka-console-producer 脚本以查看是否可以从主机发布sub。

vkc1a9a2

vkc1a9a24#

您可以为容器创建一个docker网络,然后容器将能够解析彼此的主机名并进行通信。
注意:这在docker compose和独立容器中都可用

相关问题