KAFKA-使用代理进行跨网络访问采坑记录

问题背景:

client机器是在内网的,无法直接访问到kafka的机器,所以需要走个代理机器,代理服务器可以同时被内网和外网访问。

在外网中,kafka集群都已经搭建好,生产者、消费者都可以正常运行。

问题来了:内网的client机器通过nginx代理访问kafka时候

查看topic列表正常:kafka-topics.sh --zookeeper localhost:2181 --list

创建topic正常:kafka-topics.sh --zookeeper localhost:2181 --create --topic emmp_eva_time --partitions 2  --replication-factor 2

但是生产者和消费者均异常:报错信息忘记截图了,大概的意思就是连接超时

 

解决思路:

很明显是网络层面的问题,首先,我们来看看kafka的交互的原理:

原理文章这篇写的比较好:

盗一张图:

KAFKA-使用代理进行跨网络访问采坑记录_第1张图片

1. producer 先从 zookeeper 的 "/brokers/.../state" 节点找到该 partition 的 leader
2. producer 将消息发送给该 leader
3. leader 将消息写入本地 log
4. followers 从 leader pull 消息,写入本地 log 后 leader 发送 ACK
5. leader 收到所有 ISR 中的 replica 的 ACK 后,增加 HW(high watermark,最后 commit 的 offset) 并向 producer 发送 ACK

可以看出来,kafka的生产者是二次交互的,第一次kafka集群中,zk里面拿到真实的topic的partion的leader地址,然后再真正的将数据直接写到partition的leader中。

问题就在于第一次交互后,返回的地址是什么地址

需要查看kafka的配置:conf/servier.properties

一般默认只会配置

listeners=PLAINTEXT://:9092
如果是这样的话,默认是0.0.0.0
返回给生产者或者消费者的会是本地的机器名称
如果配置了IP,则会将IP地址返回

这样的结果就是:第一次到kafka的时候返回了一个真实的kafka的ip。导致第二次交互的时候。client直接去访问kafka cluster,结果就挂了

KAFKA-使用代理进行跨网络访问采坑记录_第2张图片

解决方案:

kafka对跨网络的访问有一个专门的参数:
advertised.listeners=PLAINTEXT://hostname:9092
这个参数如果配置了,默认返回给生产者或者消费者的就是这个参数的内容 

在服务端配置域名映射:本机IP hostname 

在客户端里配置域名映射: 代理IP hostname

当第一次访问kafka后,返回的是一个域名,这样第二次访问的时候,客户端会解析这域名,于是又访问到代理服务器,

最终访问到真实机器,链路畅通。

 

问题其实不太复杂,解决问题过程中,出现了点插曲,机器的域名太复杂,由于内外网隔离没办法复制,手敲域名的过程中把l和1敲错了,导致这个方案一直没有实现成功。各种查阅深层次原理,尝试参数,tcpdump抓包,一番折腾,最终才发现是域名配置错误了,花费大半天时间。年纪大的程序员深感时间的宝贵,欢迎大家交流。

 

 

你可能感兴趣的:(kafka,踩坑,kafka,spark,分布式代理,kafka网络原理,kafka生产者)