3. 网络与连接故障:生产者/消费者连接超时、网络分区、防火墙与安全组配置问题
网络问题,说实话,是Kafka故障里最让人头疼的一类。为什么?因为很多表象是“客户端报错”,根因却在网络链路的某个角落。我见过太多团队花了一整天查代码,最后发现是安全组规则写错了。
这一章,咱们就把网络连接相关的坑,一个一个踩明白。
3.1 连接超时:客户端到底卡在哪了?
生产者报 TimeoutException,消费者报 Connection refused,这种告警你肯定见过。但超时发生在哪个环节,很多人没细想过。
我习惯把连接超时分成三类:
| 超时类型 | 典型报错 | 常见根因 |
|---|---|---|
| DNS解析超时 | UnknownHostException | DNS服务器不可用、hosts文件配置错误 |
| TCP握手超时 | connect timed out | 防火墙拦截、安全组未放行、网络不通 |
| 应用层超时 | Request timeout | Broker负载高、acks=all时副本同步慢 |
你看,同样是超时,排查方向完全不同。我曾经遇到一个案例:生产者偶尔报超时,但网络ping是通的。查了半天,发现是客户端所在容器DNS缓存过期,解析到了旧的Broker IP。那台机器早就下线了。
telnet broker_ip 9092 测试端口连通性。如果telnet通但客户端报超时,大概率是应用层问题;如果telnet不通,先查防火墙和安全组。
3.2 网络分区:集群“脑裂”了吗?
网络分区,说白了就是集群里一部分Broker互相联系不上了。Kafka依赖ZooKeeper(或KRaft)来维持集群一致性。一旦发生网络分区,可能会出现“脑裂”现象——两个分区各自选出了Controller。
嗯,这里要注意:Kafka的Controller选举机制本身有防脑裂设计(epoch机制),但网络分区仍然会导致严重问题:
- 分区副本ISR收缩:Leader无法同步给远程机架的Follower,ISR只剩Leader自己。
- 客户端连接漂移:客户端可能连到被隔离的Broker,拿到过期的元数据。
- 生产/消费延迟飙升:Leader等待ACK超时,重试次数暴增。
我记得有一次,机房A和机房B之间的专线光缆被挖断了。集群里一半Broker失联,Controller在30秒内触发了3次选举。那段时间,所有写入都超时,消费者也拉不到数据。事后复盘,我们加了一个关键配置:unclean.leader.election.enable=false,宁可不可用,也不要丢数据。
min.insync.replicas 设成1,配合 acks=all。网络分区时,Leader自己就是ISR,写入成功但数据实际上没副本。分区恢复后,数据直接丢失。这个组合一定要避免。
3.3 防火墙与安全组:看不见的“隐形墙”
防火墙和安全组配置问题,是Kafka网络故障里最常见的“低级错误”。但低级不代表好查。我见过一个案例:开发环境一切正常,上了生产就报连接超时。最后发现,生产环境的安全组只放行了9092端口,但Kafka内部通信还需要9093(Inter-broker)、2181(ZooKeeper)等端口。
下面这张图,帮你理清Kafka集群需要开放的端口关系:
配置安全组时,我建议遵循最小权限原则:
- 客户端到Broker:放行9092(或你自定义的listeners端口)
- Broker到Broker:放行9093(inter.broker.listener.name对应的端口)
- Broker到ZooKeeper:放行2181、2888、3888
- 监控系统到Broker:放行9999(JMX端口)
advertised.listeners 配置了内网IP,但客户端从公网连接。客户端拿到的是内网IP,自然连不上。解决办法:配置双监听器,内网用内网地址,公网用公网地址。
3.4 实战排查步骤
遇到网络连接故障,我一般按这个顺序排查:
- 确认客户端能解析Broker地址:
nslookup broker_hostname,看返回的IP对不对。 - 测试端口连通性:
telnet broker_ip 9092,不通就查防火墙。 - 检查Broker端监听地址:
netstat -anp | grep 9092,确认Broker确实在监听。 - 查看Broker日志:搜索
Connection refused或Socket error,往往有直接线索。 - 抓包分析:
tcpdump -i eth0 port 9092,看TCP握手是否完成。
嗯,这里要特别提醒:别忽略 advertised.listeners 和 listeners 的区别。前者是告诉客户端“你该连哪个地址”,后者是Broker自己监听的地址。两者不一致,客户端永远连不上。
listeners 配了 PLAINTEXT://0.0.0.0:9092,但 advertised.listeners 忘了配。结果客户端拿到的是Broker主机名,DNS解析到了另一个网段的IP,网络策略没放行,全线超时。这个坑,配完一定要用客户端工具验证一下。
3.5 网络故障的“隐形杀手”:TCP参数
有些网络问题,防火墙和安全组都对了,但还是间歇性超时。这时候,你可能遇到了TCP层面的“隐形杀手”。
| 参数 | 默认值 | 影响 |
|---|---|---|
| tcp_keepalive_time | 7200秒 | 连接空闲2小时才发探测包,长连接断开发现慢 |
| tcp_retries2 | 15次 | 重试15次约15分钟,超时感知极慢 |
| net.ipv4.tcp_syn_retries | 6次 | SYN重试6次约127秒,连接建立慢 |
我建议在Kafka服务器上调整这些参数:
# /etc/sysctl.conf 追加
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_retries2 = 5
net.ipv4.tcp_syn_retries = 3
# 生效
sysctl -p
调整后,连接断开能在30秒内发现,而不是等15分钟。你想想看,如果Broker宕机了,客户端要等15分钟才知道,那数据延迟得有多严重?
net.core.somaxconn 建议调到1024以上,避免高并发时连接队列溢出。
网络与连接故障,说白了就是“连不上”和“连上了但慢”。大部分问题出在配置不一致或防火墙遗漏。记住:先验证连通性,再查配置,最后调内核参数。按这个顺序来,能省下大量排查时间。