很多人都因为配置kafka外网转发而困扰,我这里统一讲一下原理和原因。
场景假设
比如你有一个kafka集群,在阿里云上,该集群有2个broker,A
和B
。
kafka集群:
A
内网:172.10.0.2 外网:10.0.21.1B
内网: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:9092
和10.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:9092
和11.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:9092
和kafka-2:9092
,通过客户端配置的hosts映射,都转成了对应的外网的ip,因此就可以访问了。
注意:
- 端口要一致,hosts映射只转ip。
- 端口不能共用,每个转发对应一个端口。
请教下,单网卡,通过NAT配置内、外网IP的场景,如何保证外网服务能够通过外网IP连接kafka集群呢?
三个kafka集群,按照如下方式配置,发现内、外网的kafka连接工具都无法正常连接集群了。
listeners=PLAINTEXT://内网IP:9092 advertised.listeners=PLAINTEXT://外网IP:9092
这个问题的重点应该在于单网卡,通过NAT映射出的一个外网IP。
除了配置域名,还有其他方式吗?
上面已经说了原理了,目前没有其他方式了。
端口不一致要怎么办??比如这里11.10.21.1:12340 -> 10.0.21.1:10002
关注文章核心,你获取到的是kafka配置的ip和端口列表,所以你需要把这个
ip+端口
进行转发,其他的都是假象。在虚拟机中,通过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
你宿主机也是有ip的。
我是试过配了宿主机ip的,
listeners=PLAINTEXT://10.0.2.5:9092 advertised.listeners=PLAINTEXT://本机ip:9092
这么配连虚拟机内网的消费者生产者都启动不了,宿主机和虚拟机用的是nat端口转发,不是用的桥接模式的,这相当于两个不同的局域网,宿主机不能直接访问虚拟机的网络
你在仔细读读这篇文章,你核心还没抓到。
用域名配置的方式,我也是试过了,也不行的
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:9092,127.0.0.1:9093,127.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
但是上面消费数据的时候就阻塞了,没法消费数据
端口导致的,域名只解决ip,把端口也对应上。
那是怎么对应啊?能给个代码吗
你在虚拟机里执行消费者命令,看看是否正常。
你用生产者命令试试,我怀疑你的topic里是空的。
我看你的问题,越来越糊涂了。
宿主机上创建了3个虚拟机,正常情况下,宿主机是可以直接访问3个虚拟机里的kafka集群的。
你到问题专区提问吧,这里说不清楚,详细描述下吧。
虚拟机上面执行是正常的,可以在虚拟机上生产消费数据,专区提问在哪?
https://www.orchome.com/kafka/issues
点击发布后,我查看问题,怎么还是,“处于草稿编辑状态,仅自己可见,点击继续 编辑”。。。
额,凌晨的时候做了限制,防止机器人灌水。
现在你在发布一下。
https://www.orchome.com/10383
我改成了用nginx代理kafka集群,进行转发访问了。目前还是每没有消费到虚拟机的kafka集群
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,却不能发送消息。 不知道为什么??
你在仔细读读这篇文章,因为你虽然访问的是外网地址,但是客户端发现的是内网的地址。你要把内网kafka地址也转过去才行
博主你好,你的文章我仔仔细细看了几遍! 感谢你的回复! 我还是有点不明白,因为我的网络环境跟你文章说的不一致! 我只有a机器有内外,通过a机器做 端口+ip 转发到内网的kafka集群! centos的防火墙策略是用 rich-rules , 别人用a机器的外网地址访问,通过防火墙策略转发到内网ip + 端口 的。
博主,这样的情况还如何把内网地址转过去,我这种情况转过去的是外网ip吧
能说下我这种情况的方案吗
这... 其实是一样的,那好吧,我根据你的情况解释一下文章的核心
你的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:注意,你的端口也要转发
不行,不行。都试过了,还是不行。能加个qq,远程我机器操作下吗
这个问题,解决了,特地来解释下:
一、通过域名配置的配置
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
二、采用外网ip的方式
只需要把上面的 advertised.listeners=PLAINTEXT://kafka-01:29092
改成 advertised.listeners=PLAINTEXT://外网ip:29092
不需要在客户端配置 hosts
结论:这样jva代码中,连接kafka的配置,如下
外网ip:29092,外网ip:39092,外网ip:49092
最终还是选择了域名的形式。
还是要谢谢大佬,我上面的评论,我又改了下,把域名,改成了外网ip,这样客户端就不用配置域名了。
这里面涉及的问题,还要给kafka 单独配置 port
赞,你之前没成功,是因为端口吧?
另外,
advertised.listeners
已经弃用了,你可以改成:listeners = PLAINTEXT://kafka-03:49092
嗯。
请问你知道内外网映射的端口不一致怎么处理吗,就比如内网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
你排查一下为什么被占用了。
服务端有三台,其中一台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)
listeners=PLAINTEXT://{内网地址}:11092
单节点kafka,配置内网就可以了,外网默认就可以访问到了。
多节点就按照文章的来。
大佬,实际是三个节点的集群,但是现在只有一台机器又外网ip,想问问有什么解决方案
用的版本是kafka_2.12-2.8.0,不知道和版本是不是有关系
只有一个外网出口...这做不到额。
因为客户端要和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的时候却是报错了
到问题区描述一下报什么错吧。
映射外网之后端口不一致,这个怎么解决
ip一样端口不一样就写成172.10.0.1 kafka-1 kafka2 11.10.21.1 kafka-1 kafka-2就好了