Skip to content

网络案例:连接失败与建立缓慢 ​

案例说明: 本页日期、业务背景、指标和工具输出均为构造或匿名化教学数据;除引用一手资料外,不应视为可核验的真实事件。排查方法与命令仍需结合目标 JDK、系统和生产变更流程验证。

这组案例关注「连接建不起来」和「建连很慢」两类现象。它们常被笼统归为「网络不通」,但根因可能在 DNS、TCP 建连、监听端口、连接队列或防火墙策略任一环节。关键是把现象拆成握手时序,再定位是哪一段断了。

案例一:connect timed out 还是 connection refused ​

1.1 事故背景 ​

某支付网关在灰度一台新节点后,调用下游清算服务开始间歇性失败。失败请求里同时出现 connect timed out 和 connection refused,运维凭直觉重启了下游,但故障没有消失。

1.2 第一步:两个异常分开看 ​

bash
# 在服务端抓握手,只看 SYN/FIN/RST
tcpdump -i eth0 'tcp[tcpflags] & (tcp-syn|tcp-fin|tcp-rst) != 0' -w /tmp/hs.pcap

抓包之后区分两种报文结局:

txt
# 结局 A:只有 [S] 没有 [S.],随后本地超时
10:00:01.100 IP 10.0.1.1.50010 > 10.0.1.2.9090: Flags [S], seq 1000
10:00:02.100 IP 10.0.1.1.50010 > 10.0.1.2.9090: Flags [S], seq 1000   # SYN 重传
10:00:04.100 IP 10.0.1.1.50010 > 10.0.1.2.9090: Flags [S], seq 1000   # 再重传

# 结局 B:对端立刻回 [R]
10:00:05.200 IP 10.0.1.1.50010 > 10.0.1.2.9090: Flags [S], seq 2000
10:00:05.201 IP 10.0.1.2.9090 > 10.0.1.1.50010: Flags [R.], seq 1, ack 2001

结局 A 对应 connect timed out,说明 SYN 没有收到 SYN+ACK,可能是路径丢包、回程路由异常或中间策略静默丢弃。结局 B 对应 connection refused,说明对端内核在目标端口没有任何监听进程,直接回了 RST。

这两个不是同一种故障。结局 B 的 refused 指向「端口没进程」,结局 A 的 timed out 指向「握手路径不通」。把它们混为一谈,就会像本案例一样去重启下游,却没注意到新节点根本没有监听 9090。

1.3 第二步:核对监听与 DNS ​

bash
# 服务端确认端口是否真的在监听
ss -tlnp | grep 9090

# 客户端确认解析到的地址是不是那台新节点
getent hosts clearing-service.internal

ss -tlnp 在新节点上没有任何输出,而 getent 返回的 IP 正是刚灰度的节点。根因是灰度脚本漏掉了服务启动步骤,端口从未监听。防火墙静默丢包更常表现为超时而非拒绝,这一点也反向说明此处不是策略问题。

1.4 根因与修复 ​

这是「服务没起来」而非「网络断了」。修复是补上启动步骤并加健康探针,DNS 解析本身没有错。教训是把 refused 和 timed out 当成同一个根因,会让你在错误的方向上反复重启。

案例二:SYN 队列满导致的建立缓慢 ​

2.1 事故背景 ​

某秒杀活动开始瞬间,新连接建立耗时从个位数毫秒飙到数秒,但建连成功后交易正常。问题只在洪峰前几十秒出现。

2.2 第一步:看握手时延与队列 ​

bash
# 统计各状态连接数
ss -s
txt
TCP:   32000 (estab 8000, closed 0, orphaned 0, timewait 0, synrecv 8000)
                                                          ↑ 异常,synrecv 堆积

synrecv 大量堆积说明服务端收到了 SYN,但第三次握手没有完成,半开连接卡在 SYN_RECV。

2.3 第二步:看内核队列上限 ​

bash
# 全连接与半连接队列上限(取值随内核版本变化,以下仅为示例量级)
sysctl net.ipv4.tcp_max_syn_backlog
ss -lnt | grep 8080        # 看 Recv-Q/Send-Q,Recv-Q 接近 Send-Q 说明 accept 队列满

洪峰下新 SYN 速率超过应用 accept() 速度,tcp_max_syn_backlog 与 listen 队列被填满,后续 SYN 被丢弃或延迟应答,表现为建连缓慢。注意:不能仅凭 timewait 多为空就排除队列问题,本案恰恰是 synrecv 堆积而非 TIME-WAIT。

2.4 根因与修复 ​

根因是短时间的 SYN 速率超过 accept 队列处理能力,不是端口耗尽也不是 GC。临时提高 tcp_max_syn_backlog 与 somaxconn、并加快应用 accept 循环后恢复。这个案例说明「建连慢」要看队列而非只看连接总数。

案例三:防火墙静默丢包伪装成超时 ​

3.1 事故背景 ​

跨可用区迁移后,一类目标 IP 的请求稳定超时,但 telnet 手动测试有时能通。故障具有目标地址选择性。

3.2 第一步:双向抓包确认丢在哪一侧 ​

bash
# 客户端抓
tcpdump -i eth0 host 10.2.3.4 and port 8080 -w /tmp/client.pcap
# 服务端同步抓
tcpdump -i eth0 host 10.1.2.3 and port 8080 -w /tmp/server.pcap
txt
# 客户端看到完整的 [S],但没有 [S.]
# 服务端抓包里根本看不到这个 [S]

客户端发出了 SYN,服务端完全没收到,说明包在中间路径被丢弃。手动 telnet 偶尔能通,是因为不同目标地址走了不同策略链路,并非连接本身没问题。

3.3 第二步:定位策略而非猜网络 ​

bash
# 核对本地与中间策略(示例命令,具体以环境为准)
iptables -L -n -v
ip route get 10.2.3.4

迁移后新增的网段没有同步到安全组规则,对应流量被静默丢弃。静默丢包的典型特征就是 timed out 而非 refused,且单向抓包能看到 SYN 无响应、对端完全无记录。

3.4 根因与修复 ​

根因是安全组漏配,不是服务或 JVM 问题。修复是补齐网段规则。这个案例提醒:跨可用区或迁移后的「选择性超时」,优先用双向抓包证明丢包位置,再去找策略,而不是先怀疑应用。

上一页: 网络性能分析与故障排查下一页: 请求超时与延迟案例返回: 网络性能分析与故障排查

Released under the MIT License.