kafka的listeners和advertised.listeners,配置内外网分流

·  阅读 3361

总结一句话

  1. listeners 指明 kafka 当前节点监听本机的哪个网卡
  2. advertised.listeners 指明客户端通过哪个 ip 可以访问到当前节点

1. kafka的两个配置listeners和advertised.listeners

1.1 listeners:

kafka监听的网卡的ip,假设你机器上有两张网卡,内网192.168.0.213和外网101.89.163.1 如下配置

listeners=PLAINTEXT://192.168.0.213:9092
复制代码

那么kafka只监听内网网卡,即只接收内网网卡的数据,如果如下配置:

listeners=PLAINTEXT://101.89.163.1:9092
复制代码

那么kafka只监听外网网卡,即只接收外网网卡的数据。
当然ip可以配置成0.0.0.0,监听所有网卡。
总结
listeners 解决的是 kafka 监听来自于哪个网卡的请求。

1.2 advertised.listeners

一般配置成这样:

listeners=PLAINTEXT://192.168.0.213:9092
advertised.listeners=PLAINTEXT://101.89.163.1:9092
复制代码

配置过 zookeeper 的都知道, zookeeper 的配置文件中写明了所有 zookeeper 节点的 ip 地址,以便启动后节点之间的互相通信。我们观察 kafka 的配置文件 server.properties,会发现里面并没有记录其他 kafka 节点的地址,即各个节点都不知道其他节点的 ip 地址。那么 kafka 集群的各个节点之间是怎么通信的呢?
kafka 节点启动后,会向 zookeeper 注册自己,同时告诉 zookeeper 自身的通信地址,这个地址就是配置文件中的 advertised.listeners,如果没有配置 advertised.listeners,就会使用listeners。同时从 zookeeper 中获取兄弟节点的这个地址,以便与兄弟节点通信。即 kafka 节点是从 zookeeper 获取的其他节点的通信地址。
我们使用客户端以一个 ip 地址首次连接 kafka 节点后,节点返回给客户端的 kafka 集群地址就是从 zookeeper 中获得的这些地址,也就是各个节点配置的 advertised.listeners,包括当前连接的节点。所以可能客户端后续访问当前节点的 ip 地址有可能和首次连接的 ip 地址并不一样。

2. 三种情景,搭配使用这两个配置

2.1. 只需要内网访问kafka

这个很简单,只配置 listeners 并且使用内网 ip

listeners=PLAINTEXT://192.168.0.213:9092
复制代码

客户端访问 kafka 节点,以及与其他节点通信都用这个 ip 地址。

2.2 需要外网访问

2.2.1 机器有外网网卡

最简单的一个方法,只配置 listeners 并且使用外网 ip

listeners=PLAINTEXT://101.89.163.1:9092
复制代码

所有请求都走外网网卡,虽然有问题(所有流量走外网),但是能够正常使用。

2.2.2 机器没有外网网卡

如果机器是通过转发或者映射搞出来的外网ip(例如你访问腾讯新闻某个页面使用的 ip,这个 ip 和实际的网卡并不在为你提供首页内容的那台机器上),此时kafka无法监听这个外网ip,启动就会报错。
需要配置一下 advertised.listeners,例如:

listeners=PLAINTEXT://192.168.0.213:9092
advertised.listeners=PLAINTEXT://101.89.163.1:9092
复制代码

此时 kafka 客户端访问 kafka 集群的一个完整流程是:

  1. 客户端访问 101.89.163.1:9092,该请求被发送到 kafka 节点宿主机的内网地址 192.168.0.213:9092 上(也可以是其他 kafka 节点,效果是一样的),第一次请求成功,此次请求申请获得 kafka 集群的所有节点的地址。
  2. kafka 从 zookeeper 拿到自己和其他兄弟节点注册在 zookeeper 的 advertised.listeners,作为 kafka 集群各个节点的的服务 ip 返回给客户端。
  3. 客户端拿这些返回的服务 ip 访问kafka集群,该请求从 实际拥有该 ip 的机器被转发到被具体 kafka 节点所在的内网ip,访问到了 kafka 节点,

当然有外网网卡时你也可以配置

listeners=PLAINTEXT://101.89.163.1:9092
advertised.listeners=PLAINTEXT://101.89.163.1:9092
复制代码

但是这毫无意义。

2.2.3 为什么客户端需要在第一次请求中获取 kafka 各个节点的服务 ip

因为你可以在启动客户端时只配置一个 kafka 节点的地址而不是列出所有节点(这样是不推荐的),但是客户端必须具有访问集群中的每一个节点的能力(收消息、发消息都可能面向所有节点)。
对于 2.2 的情况,如果去掉

advertised.listeners=PLAINTEXT://101.89.163.1:9092
复制代码

你会发现虽然你在启动 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

3. 内外网分流

2中两种情况都有一个问题,所有请求包括 kafka 节点之间的通信都走的外网,这既不方便(外网访问的各种权限控制很麻烦),也不经济,更不安全。
这时候就要配置内外网。
配置1(针对没有实际的外网网卡,即2.2的情况):

listener.security.protocol.map=INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT
listeners=INTERNAL://192.168.0.213:9092,EXTERNAL://192.168.0.213:19092
advertised.listeners=INTERNAL://192.168.0.213:9092,EXTERNAL://101.89.163.9:19092
inter.broker.listener.name=INTERNAL
复制代码

配置2(针对有实际的外网网卡,即2.1的情况):

listener.security.protocol.map=INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT
listeners=INTERNAL://192.168.0.213:9092,EXTERNAL://101.89.163.9:19092
advertised.listeners=INTERNAL://192.168.0.213:9092,EXTERNAL://101.89.163.9:19092
inter.broker.listener.name=INTERNAL
复制代码

这两配置的区别是只有 listeners 的 EXTERNAL 使用的 ip 不一样,一个使用内网 ip ,一个使用外网 ip 。
对内网 INTERNAL 的配置就不说了,主要用于节点间通信,无论 listeners 还是 advertised.listeners 都配置成内网 ip,自然所有请求都走内网;主要是外网 EXTERNAL 配置: 1)如果机器的外网 ip 是映射来的,listeners 的 EXTERNAL 使用内网ip,客户端拿到的是 advertised.listeners 配置的外网 ip,对于该外网 ip 的请求会被转发到对应的内网 ip,即访问到了对应的 kafka 节点,请求完成闭环。不要问怎么转发的,既然机器被映射了外网 ip,自然能够转发,有问题问网管 2)如果你的kafka宿主机有外网网卡,listeners 的EXTERNAL 使用用外网ip,客户端拿到的是 advertised.listeners 配置的外网 ip,直接就访问到了对应的 kafka 节点。

分类:
后端
标签:
分类:
后端
标签:
收藏成功!
已添加到「」, 点击更改