上个月接了个新项目,需要用Kafka做消息队列。想着Kafka部署应该挺简单的,Docker拉个镜像,配置几个参数就完事了。
结果现实又给了我一记响亮的耳光。
项目用的Spring Boot,按照网上的教程配置了Kafka:
spring:
kafka:
bootstrap-servers: localhost:17124,localhost:17125,localhost:17126启动项目,直接报错连不上。我心想肯定是端口或者网络问题,检查了半天:
就是连不上!
后来我才发现,连接不上的问题主要出在IP和端口不可达。
因为我用的是Docker部署,容器内的Kafka监听的是内部端口,但是外部访问需要通过端口映射。检查了Docker配置,发现端口映射有问题:
# 检查容器端口映射
docker ps映射的端口和配置文件里的端口不一致!改正端口映射后,连接问题解决了。
能连上Kafka了,但是创建Topic的时候又出问题了,一直超时。
这个问题和上面的连接问题不一样。能连上说明基础网络是通的,但是操作Broker的时候就不行了。
我去看了Kafka的配置文件server.properties:

看到这个配置我就明白问题出在哪里了:
advertised.listeners=PLAINTEXT://acowbo-data-center-kafka-one:9092我用了容器名称acowbo-data-center-kafka-one作为地址!
这就是问题所在:客户端能通过端口映射连接到Kafka,但是Kafka告诉客户端要连接acowbo-data-center-kafka-one:9092这个地址。而客户端根本不知道这个容器名称是什么,当然就连不上了。
advertised.listeners的作用就是告诉客户端:"你要跟我后续通信,就连这个地址"。
工作流程是这样的:
bootstrap-servers连接到Kafkaadvertised.listeners中配置的地址advertised.listeners中的地址如果advertised.listeners配置的地址客户端连不上,就会出现能连接但是操作超时的问题。
# 原来的配置(有问题)
advertised.listeners=PLAINTEXT://acowbo-data-center-kafka-one:9092
# 修改为可访问的IP地址
advertised.listeners=PLAINTEXT://192.168.1.100:17124这里要用客户端能够访问到的真实IP地址和端口,不能用容器名称。
如果Kafka部署在Docker里,advertised.listeners不能用容器内部的地址,要用:
比如我的配置:
那么advertised.listeners就应该配置为:192.168.1.100:17124
配置Kafka网络参数的时候,有几个重要的注意事项:
1. advertised.listeners的前缀要唯一
# ❌ 错误:两个PLAINTEXT前缀
advertised.listeners=PLAINTEXT://192.168.1.100:17124,PLAINTEXT://192.168.1.100:17125
# ✅ 正确:不同的前缀
advertised.listeners=INTERNAL://192.168.1.100:17124,EXTERNAL://192.168.1.100:171252. 所有前缀都要在listener.security.protocol.map中定义
advertised.listeners=INTERNAL://192.168.1.100:17124,EXTERNAL://192.168.1.100:17125
listener.security.protocol.map=INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT如果advertised.listeners里用了INTERNAL和EXTERNAL,那么listener.security.protocol.map里就必须都有对应的定义,否则Kafka启动就会报错。
经过这番折腾,我的最终配置是这样的:
# 监听配置
listeners=PLAINTEXT://0.0.0.0:9092
advertised.listeners=PLAINTEXT://192.168.1.100:17124
# 安全协议映射
listener.security.protocol.map=PLAINTEXT:PLAINTEXT
# 其他必要配置
broker.id=0
log.dirs=/kafka/kafka-logs
zookeeper.connect=192.168.1.100:12181这样配置后,无论是连接还是Topic操作都正常了。
如果用Docker部署Kafka,一定要确保:
listeners配置一致advertised.listeners配置一致这是我踩的最大的坑。容器名称只在Docker网络内部有效,外部客户端根本解析不了。一定要用真实的IP地址和端口。
advertised.listeners中每个前缀必须唯一listener.security.protocol.map中有对应定义部署Kafka之前,先搞清楚网络拓扑:
搞清楚这些,配置就不会出错了。
现在我部署Kafka都会:
advertised.listeners就要有对应的listener.security.protocol.map这些坑我都踩过了,希望大家能少走点弯路。
提醒:如果你现在的Kafka配置用的是容器名称或者localhost,赶紧检查一下,别等客户端连不上了再改!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。