使用Docker部署Kafka后生产者报KafkaTimeoutError问题求解
我来帮你排查这个问题——你遇到的KafkaTimeoutError本质上是生产者无法从Kafka集群获取元数据,核心原因和你启动容器时的ADVERTISED_HOST配置以及生产者的连接方式有关。
问题根源分析
当你用docker run启动spotify/kafka时,设置了ADVERTISED_HOST=192.168.99.100,这个参数是Kafka用来告诉客户端(你的生产者)“请用这个地址来和我通信”的关键配置。现在你的生产者直接连接容器IP172.17.0.2:9092,虽然能ping通容器,但Kafka返回给生产者的元数据里的broker地址是192.168.99.100:9092,如果你的生产者所在环境无法访问这个地址,就会出现超时错误。
具体解决方案
下面是两种可行的解决办法,你可以根据自己的环境选择:
方法一:修改生产者的bootstrap_servers为ADVERTISED_HOST地址
既然Kafka配置的对外通告地址是192.168.99.100:9092,那直接让生产者用这个地址连接就行:
from kafka import KafkaProducer producer = KafkaProducer(bootstrap_servers='192.168.99.100:9092') for i in range(100): producer.send('foobar', b'hola') producer.close()
注意:确保你的生产者所在机器能访问192.168.99.100:9092,因为你已经做了端口映射-p 9092:9092,所以只要这个地址能通,就能正常连接。
方法二:调整Docker容器的ADVERTISED_HOST为容器IP(适合本地测试)
如果你只是在本地测试,想直接用容器IP连接,可以修改启动命令的ADVERTISED_HOST为容器的IP172.17.0.2,同时重启容器:
docker run -p 2181:2181 -p 9092:9092 --env ADVERTISED_HOST=172.17.0.2 --env ADVERTISED_PORT=9092 spotify/kafka
之后再运行你原来的生产者代码,就能正常发送消息了。
额外提示:用localhost连接(适合Docker运行在本地主机的场景)
如果你的Docker是直接运行在本地主机(不是Docker Machine),还可以把ADVERTISED_HOST设为localhost,然后生产者用localhost:9092连接:
启动命令:
docker run -p 2181:2181 -p 9092:9092 --env ADVERTISED_HOST=localhost --env ADVERTISED_PORT=9092 spotify/kafka
生产者代码:
from kafka import KafkaProducer producer = KafkaProducer(bootstrap_servers='localhost:9092') for i in range(100): producer.send('foobar', b'hola') producer.close()
验证方法
不管用哪种方法,你可以先通过telnet或者nc命令测试连通性,比如:
telnet 192.168.99.100 9092
如果能连通,再运行生产者代码,基本就能解决超时问题了。
内容的提问来源于stack exchange,提问作者Derk

