我正在为应用程序编写端到端测试。我启动了一个应用程序实例,一个Kafka实例和一个Zookeeper(均已Docker化),然后与应用程序API交互以测试其功能。我需要在此应用程序中测试事件使用者的功能。我发布了测试中的事件,应用程序有望处理这些事件。
问题:如果我在本地(不在Docker中)运行应用程序并运行会产生事件的测试,则应用程序代码中的使用者可以正确处理事件。在这种情况下,使用者和测试已bootstrapServers
设置为localhost:9092
。但是,如果应用程序作为Dockerized实例运行,则不会看到事件。在这种情况下bootstrapServers
,kafka:9092
在应用程序和localhost:9092
测试中将设置为kafka
Docker容器名称。该kafka
容器暴露它的9092
端口,使卡夫卡的同一个实例可以从泊坞窗容器内,并从主机(运行我的测试)来访问主机。
代码中的唯一区别是localhost
vskafka
设置为引导服务器。在这两种情况下,消费者和生产者都可以成功启动;事件发布没有错误。只是在一种情况下,消费者没有收到事件。
问题:如何使Docker化的使用者看到从主机发布的事件?
注意:我有一个配置正确的Docker网络,其中包括应用程序实例,Zookeeper和Kafka。他们都互相“见”。的相应的端口kafka
和zookeeper
被暴露到主机。卡夫卡港口: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
设置为INSIDE和OUTSIDE通信的不同端口的env变量有关。解决方案是在Docker容器中运行应用程序代码时使用正确的端口。
这类问题通常与Kafka处理经纪人地址的方式有关。
当您启动Kafka经纪人时,它会绑定自己0.0.0.0:9092
并使用地址在Zookeeper上注册<hostname>:9092
。与客户建立联系时,将与Zookeeper联系以获取特定经纪人的地址。
这意味着,当您启动Kafka容器时,会遇到以下情况:
现在,如果您从kafkanet网络内部的容器中将客户端连接到Kafka,则从Zookeeper返回的地址就是kafka:9092
可以通过kafkanet
网络解析的地址。
但是,如果您从外部docker连接到Kafka(即使用localhost:9092
docker映射的终结点),您仍会获取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端口映射来访问Kafka代理。
但是从我的理解来看,您只需要此设置即可测试所有内容,因此最简单的方法是“欺骗”位于docker外部的系统。使用上面指定的命名,这意味着只需将/etc/hosts
line添加到您(或Windows等效)中127.0.0.1 kafka.kafkanet
。
这样,当您居住在docker外部的客户端连接到Kafka时,将会发生以下情况:
kafka.kafkanet
kafka.kafkanet
为127.0.0.1编辑
正如在评论中指出,新版本的卡夫卡现在使用的概念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
主机名和端口。
在这两种情况下,如果未指定,它们将由代理自动使用运行代理的计算机的主机名派生。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句