欢迎关注笔者的微信公众号


今天在云服务器搭建kafka测试环境然后远程连接出现问题,在命令行中可以正常创建生产者,消费者以及topic,但是通过代码远程连接是就出现问题。经过排查最终发现是`advertised.listeners`和`listeners`这两个配置的原因。 出现这个问题的原因是云服务器通常都有两个IP,一个公网ip,一个内网ip.之前在虚拟机或者局域网环境中搭建kafka环境时都是用同一个ip,所以没有出现这个问题。 ## 解决办法 ```properties listeners=PLAINTEXT://0.0.0.0:9092 advertised.listeners=PLAINTEXT://公网ip/域名:9092 ``` ![](https://itbird.oss-cn-beijing.aliyuncs.com/halo/25340037-0d74-442d-a3e4-ab4372f43e3e_1640255736660.png)

原理剖析

listeners: 学名叫监听器,其实就是告诉外部连接者要通过什么协议访问指定主机名和端口开放的 Kafka 服务。
advertised.listeners:和 listeners 相比多了个 advertised。Advertised 的含义表示宣称的、公布的,就是说这组监听器是 Broker 用于对外发布的。
kafka 节点启动后,会向 zookeeper 注册自己,同时告诉 zookeeper 自身的通信地址,这个地址就是配置文件中的 advertised.listeners,如果没有配置 advertised.listeners,就会使用listeners。同时从 zookeeper 中获取兄弟节点的这个地址,以便与兄弟节点通信。即 kafka 节点是从 zookeeper 获取的其他节点的通信地址。
我们使用客户端以一个 ip 地址首次连接 kafka 节点后,节点返回给客户端的 kafka 集群地址就是从 zookeeper 中获得的这些地址,也就是各个节点配置的 advertised.listeners,包括当前连接的节点。所以可能客户端后续访问当前节点的 ip 地址有可能和首次连接的 ip 地址并不一样。

为什么客户端需要在第一次请求中获取 kafka 各个节点的服务 ip
因为你可以在启动客户端时只配置一个 kafka 节点的地址而不是列出所有节点(这样是不推荐的),但是客户端必须具有访问集群中的每一个节点的能力(收消息、发消息都可能面向所有节点)。
如果不配置advertised.listeners, 你会发现虽然你在启动 kafka 客户端时配置的访问地址是101.89.163.1:9092,但是 kafka 客户端启动时报错:

Connection to node -1[192.168.0.213:9092] could not be established. Broker may not be available.

为什么明明配置的是101.89.163.1:9092启动时连接的是192.168.0.213?这就是因为不配置advertised.listeners 则使用listeners 代替并注册到zookeeper 中,客户端拿到的 kafka 节点 ip 就是listeners配置的内网 ip 192.168.0.213。

参考文献