kafka外网转发

原创
半兽人 发表于: 2019-09-24   最后更新时间: 2023-09-05 16:34:37  
{{totalSubscript}} 订阅, 21,236 游览

很多人都因为配置kafka外网转发而困扰,我这里统一讲一下原理和原因。

场景假设

比如你有一个kafka集群,在阿里云上,该集群有2个broker,AB

kafka集群:

  • A内网:172.10.0.2 外网:10.0.21.1
  • B内网:172.10.0.1 外网:10.0.21.2

server.properties配置

config/server-1.properties: 
    broker.id=1 
    listeners=PLAINTEXT://172.10.0.1:9092

config/server-2.properties: 
    broker.id=2 
    listeners=PLAINTEXT://172.10.0.2:9092

配置内网地址即可,就可以通过外网访问了(10.0.21.1:9092 和 10.0.21.2:9092 可以通,但是如果用kafka客户端连接会报超时)

你想通过你的电脑来访问kafka集群,也就想访问10.0.21.1:909210.0.21.2:9092

注意,我额外加一层场景,转发,复杂一点,但是原理相同。

路由转发,比如:

11.10.21.1  -> 10.0.21.1
11.10.21.2  -> 10.0.21.2
  • 11.10.21.x 为又加了一层转发ip

测试

这时,如果你通过11.10.21.1:909211.10.21.2端口都是通的,但是访问kafka发送或消费消息时,会报网络超时,这是为什么呢?

因为kafka客户端是主动发现集群地址的,当你通过11.10.21.1:9092确实是连接到kafka集群了,kafka集群返回给你的ip列表是你listeners配置的,也就是

172.10.0.1:9092
172.10.0.2:9092

你的ip转发和端口都没有用,这就是所有转发外网等等的本质原因。

解决

最简单的方式是客户端通过域名映射的方式。

修改kafka集群服务端的server.properties配置

config/server-1.properties: 
    broker.id=1 
    listeners=PLAINTEXT://kafka-1:9092

config/server-2.properties: 
    broker.id=2 
    listeners=PLAINTEXT://kafka2:9092

kafka集群的服务端,配置hosts

cat /etc/hosts
172.10.0.1 kafka-1
172.10.0.2 kafka-2

本机客户端,配置hosts

cat /etc/hosts
11.10.21.1 kafka-1
11.10.21.2 kafka-2

客户端访问kafka集群时,获取的是kafka-1:9092kafka-2:9092,通过客户端配置的hosts映射,都转成了对应的外网的ip,因此就可以访问了。

注意:

  • 端口要一致,hosts映射只转ip。
  • 端口不能共用,每个转发对应一个端口。
更新于 2023-09-05
在线,23分钟前登录

流木 1年前

请教下,单网卡,通过NAT配置内、外网IP的场景,如何保证外网服务能够通过外网IP连接kafka集群呢?
三个kafka集群,按照如下方式配置,发现内、外网的kafka连接工具都无法正常连接集群了。

listeners=PLAINTEXT://内网IP:9092
advertised.listeners=PLAINTEXT://外网IP:9092

这个问题的重点应该在于单网卡,通过NAT映射出的一个外网IP。
除了配置域名,还有其他方式吗?

半兽人 -> 流木 1年前

上面已经说了原理了,目前没有其他方式了。

L-Yming 3年前

端口不一致要怎么办??比如这里11.10.21.1:12340 -> 10.0.21.1:10002

半兽人 -> L-Yming 3年前

关注文章核心,你获取到的是kafka配置的ip和端口列表,所以你需要把这个ip+端口进行转发,其他的都是假象。

早出晚归 3年前

在虚拟机中,通过nat端口转发到宿主机的这种情况下怎么配置?
虚拟机10.0.2.5:9092 转发到宿主机127.0.0.1:9092
虚拟机10.0.2.6:9092 转发到宿主机127.0.0.1:9093
虚拟机10.0.2.7:9092 转发到宿主机127.0.0.1:9094

半兽人 -> 早出晚归 3年前

你宿主机也是有ip的。

早出晚归 -> 半兽人 3年前

我是试过配了宿主机ip的,

listeners=PLAINTEXT://10.0.2.5:9092
advertised.listeners=PLAINTEXT://本机ip:9092

这么配连虚拟机内网的消费者生产者都启动不了,宿主机和虚拟机用的是nat端口转发,不是用的桥接模式的,这相当于两个不同的局域网,宿主机不能直接访问虚拟机的网络

半兽人 -> 早出晚归 3年前

你在仔细读读这篇文章,你核心还没抓到。

早出晚归 -> 半兽人 3年前

用域名配置的方式,我也是试过了,也不行的

Linux kafka_2.11-0.11.0.2集群三台机子分别配置:

server.properties配置

advertised.listeners=PLAINTEXT://hadoop01.richstone.com:9092
advertised.listeners=PLAINTEXT://hadoop02.richstone.com:9092
advertised.listeners=PLAINTEXT://hadoop03.richstone.com:9092

hosts配置

10.0.2.5   hadoop01.richstone.com
10.0.2.6   hadoop02.richstone.com
10.0.2.7   hadoop03.richstone.com

虚拟机nat端口转发

10.0.2.5:9092 转发到宿主机127.0.0.1:9092
10.0.2.6:9092 转发到宿主机127.0.0.1:9093
10.0.2.7:9092 转发到宿主机127.0.0.1:9094

宿主机配置hosts配置

127.0.0.1 hadoop01.richstone.com
127.0.0.1 hadoop02.richstone.com
127.0.0.1 hadoop03.richstone.com

windows宿主机:

Telnet 127.0.0.1:9092127.0.0.1:9093127.0.0.1:9094是通的

访问:

.\bin\windows\kafka-console-consumer.bat --topic first --bootstrap-server  hadoop01.richstone.com:9092,hadoop02.richstone.com:9093,hadoop03.richstone.com:9094 --from-beginning

但是上面消费数据的时候就阻塞了,没法消费数据

半兽人 -> 早出晚归 3年前

端口导致的,域名只解决ip,把端口也对应上。

早出晚归 -> 半兽人 3年前

那是怎么对应啊?能给个代码吗

半兽人 -> 早出晚归 3年前

你在虚拟机里执行消费者命令,看看是否正常。
你用生产者命令试试,我怀疑你的topic里是空的。

半兽人 -> 早出晚归 3年前

我看你的问题,越来越糊涂了。
宿主机上创建了3个虚拟机,正常情况下,宿主机是可以直接访问3个虚拟机里的kafka集群的。
你到问题专区提问吧,这里说不清楚,详细描述下吧。

早出晚归 -> 半兽人 3年前

虚拟机上面执行是正常的,可以在虚拟机上生产消费数据,专区提问在哪?

早出晚归 -> 半兽人 3年前

点击发布后,我查看问题,怎么还是,“处于草稿编辑状态,仅自己可见,点击继续 编辑”。。。

半兽人 -> 早出晚归 3年前

额,凌晨的时候做了限制,防止机器人灌水。
现在你在发布一下。

早出晚归 -> 半兽人 3年前

https://www.orchome.com/10383
我改成了用nginx代理kafka集群,进行转发访问了。目前还是每没有消费到虚拟机的kafka集群

易初 3年前

1、我有3台内网机器 192.168.103.194 、 192.168.103.195、 192.168.103.196 部署了 kafka 集群;
2、还有1台内网机器 192.168.103.193 有外网ip 128.135.227.178
3、在193机器上做了防火墙策略,通过访问外网,可以转发到内网kafka的端口上,防火墙策略如

rule family="ipv4" source address="128.135.227.178/24" forward-port port="29092" protocol="tcp" to-port="9092" to-addr="192.168.103.194"
rule family="ipv4" source address="128.135.227.178/24" forward-port port="39092" protocol="tcp" to-port="9092" to-addr="192.168.103.195"
rule family="ipv4" source address="128.135.227.178/24" forward-port port="49092" protocol="tcp" to-port="9092" to-addr="192.168.103.196"

5、通过访问 外网ip 连接 kafka ,如

spring:
  kafka:
    bootstrap-servers: 128.135.227.178:29092

6、发现,能创建topic,却不能发送消息。 不知道为什么??

半兽人 -> 易初 3年前

你在仔细读读这篇文章,因为你虽然访问的是外网地址,但是客户端发现的是内网的地址。你要把内网kafka地址也转过去才行

易初 -> 半兽人 3年前

博主你好,你的文章我仔仔细细看了几遍! 感谢你的回复! 我还是有点不明白,因为我的网络环境跟你文章说的不一致! 我只有a机器有内外,通过a机器做 端口+ip 转发到内网的kafka集群! centos的防火墙策略是用 rich-rules , 别人用a机器的外网地址访问,通过防火墙策略转发到内网ip + 端口 的。
博主,这样的情况还如何把内网地址转过去,我这种情况转过去的是外网ip吧
能说下我这种情况的方案吗

半兽人 -> 易初 3年前

这... 其实是一样的,那好吧,我根据你的情况解释一下文章的核心

你的java程序客户端配置的是128.135.227.178:29092(你可能配置了3个,但是没有用),这个是通的,但是kafka客户端是主动发现集群地址的,也就是拉取到的是

192.168.103.194:9092
192.168.103.195:9092
192.168.103.196:9092

在强调一遍,也就是说你的java程序是主动发现集群地址的,发现的是你的内网地址,自然就不通。

所以,你要么像上面的例子一样,都用域名的形态,或者你把内网地址在路由上在转发一遍。

192.168.103.194:9092 -> 128.135.227.178:29092 -> 真正的kafka节点
...
...

ps:注意,你的端口也要转发

易初 -> 半兽人 3年前

不行,不行。都试过了,还是不行。能加个qq,远程我机器操作下吗

易初 -> 半兽人 3年前

这个问题,解决了,特地来解释下:

一、通过域名配置的配置
1、内网3台kafka节点,server.properties 分别加了

节点1:
port=29092  
advertised.listeners=PLAINTEXT://kafka-01:29092
listeners = PLAINTEXT://0.0.0.0:29092

节点2:
port=39092  
advertised.listeners=PLAINTEXT://kafka-02:39092
listeners = PLAINTEXT://0.0.0.0:39092

节点3:
port=49092  
advertised.listeners=PLAINTEXT://kafka-03:49092
listeners = PLAINTEXT://0.0.0.0:49092

2、节点4:具备内外网ip,防火墙配置如下:

port=29092:proto=tcp:toport=29092:toaddr=192.168.103.194
port=39092:proto=tcp:toport=39092:toaddr=192.168.103.195
port=49092:proto=tcp:toport=49092:toaddr=192.168.103.196

3、客户端机器,配置hosts

192.168.103.194   kafka-01
192.168.103.195   kafka-02
192.168.103.196   kafka-03

二、采用外网ip的方式
只需要把上面的 advertised.listeners=PLAINTEXT://kafka-01:29092
改成 advertised.listeners=PLAINTEXT://外网ip:29092
不需要在客户端配置 hosts

结论:这样jva代码中,连接kafka的配置,如下

外网ip:29092,外网ip:39092,外网ip:49092
半兽人 -> 易初 3年前

最终还是选择了域名的形式。

易初 -> 半兽人 3年前

还是要谢谢大佬,我上面的评论,我又改了下,把域名,改成了外网ip,这样客户端就不用配置域名了。
这里面涉及的问题,还要给kafka 单独配置 port

半兽人 -> 易初 3年前

赞,你之前没成功,是因为端口吧?

半兽人 -> 易初 3年前

另外,advertised.listeners已经弃用了,你可以改成:

listeners = PLAINTEXT://kafka-03:49092
易初 -> 半兽人 3年前

嗯。

L-Yming -> 易初 3年前

请问你知道内外网映射的端口不一致怎么处理吗,就比如内网ip:9888对应外网ip:12340端口

大佬 我看到这边不太能理解,上面他这样配置 zk里返回的是kakfa01:29092 也就是内网192.168.103.194:29092 但是这样外网客户端获取的内网ip不应该解析不了吗 这怎么通的

其次采用外网ip的方式 advertised.listeners=PLAINTEXT://外网ip:29092 那么3节点启动的时候会报错:外网ip:29092已经被某个节点注册了

靠的是这个:

advertised.listeners=PLAINTEXT://外网ip:29092

你排查一下为什么被占用了。

秦时明月 3年前

服务端有三台,其中一台172.17.16.3有外网ip,kafka配置文件如下

host.name=172.17.16.3
advertised.listeners=PLAINTEXT://105.54.73.176:11092

如何能让外网客户端能访问到kafka集群?内网kafka集群是可以正常访问的?
之前的配置文件有加过

listeners=PLAINTEXT://:11092

但是外网客户端连接报了如下错误:

[root@localhost kafka_2.12-2.0.1]# bin/kafka-console-consumer.sh --topic measure_quantum --from-beginning --bootstrap-server 105.54.73.176:11092
[2021-05-08 10:47:29,028] WARN [Consumer clientId=consumer-1, groupId=console-consumer-69132] Error while fetching metadata with correlation id 2 : {measure_quantum=INVALID_REPLICATION_FACTOR} (org.apache.kafka.clients.NetworkClient)
半兽人 -> 秦时明月 3年前
listeners=PLAINTEXT://{内网地址}:11092

单节点kafka,配置内网就可以了,外网默认就可以访问到了。
多节点就按照文章的来。

秦时明月 -> 半兽人 3年前

大佬,实际是三个节点的集群,但是现在只有一台机器又外网ip,想问问有什么解决方案

秦时明月 -> 半兽人 3年前

用的版本是kafka_2.12-2.8.0,不知道和版本是不是有关系

半兽人 -> 秦时明月 3年前

只有一个外网出口...这做不到额。
因为客户端要和kafka对应的节点做长连接。

服务端三个节点,可以只配置kafka单个节点A对外转发吗,能不能客户端访问集群的时候只通过这一个节点A(只有一个服务器的外网ip)进行访问。目前我在3个节点的服务器上配置了节点A的hosts:172.10.0.1 kafka-1。然后客户端配置了节点A的外网hosts映射:11.10.21.1 kafka-1,连接配置bootstrap-servers: kafka-1:9092。但客户端访问节点A的时候却是报错了

到问题区描述一下报什么错吧。

倾耳倾听 5年前

映射外网之后端口不一致,这个怎么解决

ip一样端口不一样就写成172.10.0.1 kafka-1 kafka2 11.10.21.1 kafka-1 kafka-2就好了

查看kafka更多相关的文章或提一个关于kafka的问题,也可以与我们一起分享文章