网络案例:请求超时与延迟
案例说明: 本页日期、业务背景、指标和工具输出均为构造或匿名化教学数据;除引用一手资料外,不应视为可核验的真实事件。排查方法与命令仍需结合目标 JDK、系统和生产变更流程验证。
这组案例关注「请求发出去了但很久才回来」或「直接超时」。超时既可能是网络问题,也可能是对端处理慢、应用消费不及时或下游依赖变慢。难点是把「耗时花在哪一段」拆清楚,而不是把超时直接等同于网络故障。
案例一:read timed out 指向对端处理慢
1.1 事故背景
某订单服务调用风控服务,白天偶发 SocketTimeoutException: Read timed out,超时设 3 秒。网络组坚持网络没问题,因为 ping 正常、带宽空闲。
1.2 第一步:拆连接阶段和读阶段
# 服务端抓该连接的请求/响应时序
tcpdump -i eth0 host risk-svc.internal and port 8080 -w /tmp/risk.pcap10:05:00.000 client → server: [P.] 请求数据
10:05:00.001 server → client: [.] ACK(确认收到请求)
10:05:02.800 server → client: [P.] 响应数据 ← 请求到响应差 2.8 秒
10:05:02.801 client → server: [.] ACK握手很快,请求被 ACK 也很快,但从请求到响应之间的 2.8 秒全在对端处理上。ping 正常只能说明网络层可达,不能说明应用层快。
1.3 第二步:回服务端查处理耗时
# 服务端日志看该笔请求的处理时间(示例字段)
grep "risk-eval" risk.log | grep "traceId=abc"日志显示单笔风控计算耗时 2.8 秒,且高峰时线程池排队。根因是风控模型在一次规则变更后引入了慢路径,不是网络。把 read timed out 当成网络故障,会让网络组在抓包上浪费时间。
1.4 根因与修复
根因是对端应用处理慢导致读超时。修复是回滚规则变更并给风控线程池扩容。教训:read 超时先看「请求 ACK 之后响应之前的间隔」,那段耗时在对端而不是网络上。
案例二:重传与高 RTT 导致的延迟
2.1 事故背景
某跨地域调用整体 RT 偏高且抖动大,但应用处理日志显示本地处理只有十几毫秒。
2.2 第一步:看 RTT 与重传
# 按连接看 RTT 与拥塞窗口
ss -tni | grep -A1 10.9.8.7ESTAB 0 0 10.0.1.1:8080 10.9.8.7:51000
cubic ... rtt:180/40 rto:400 cwnd:3 ssthresh:2RTT 180ms 且 cwnd 只有 3 个 MSS,ssthresh 降到 2,这是典型的发生过丢包后拥塞窗口被压小的状态。再确认重传:
# Wireshark 过滤重传
tcp.analysis.retransmission存在明显重传,说明链路质量差导致窗口长期偏小,每次传输的有效吞吐被拖低,累积成高 RT。
2.3 第二步:确认是链路问题还是路由绕行
traceroute 10.9.8.7路径跳数比预期多出一倍,存在绕行节点。根因是跨地域专线切换后路由走了公网绕行,丢包抬高了 RTT 和重传,不是应用慢。
2.4 根因与修复
根因是网络路径质量,修复是纠正路由回到专线。这个案例说明「应用处理快但 RT 高」要先看 ss -tni 的 RTT/cwnd,再决定是查链路还是查代码。
案例三:应用侧消费不及时伪装成网络延迟
3.1 事故背景
某长连接网关偶发上行数据延迟,客户端显示已发出,服务端处理却晚了数秒。
3.2 第一步:看 Recv-Q 是否堆积
ss -tni | grep 10.0.2.9ESTAB 51200 0 10.0.1.1:9000 10.0.2.9:43000
↑ Recv-Q 持续 50KB 以上Recv-Q 持续偏高,表示数据已到达内核 socket 缓冲区但应用没有及时 read()。这不是网络延迟,而是应用消费慢,数据卡在内核缓冲里。
3.3 第二步:回线程栈看读线程
jstack <pid> | grep -A8 "nio-event-loop"读线程大量时间花在别的处理逻辑上,读循环被阻塞。根因是事件循环里混入了耗时同步调用,TCP 层准时收包但应用没读。
3.4 根因与修复
根因是事件循环被阻塞导致消费不及时,不是网络。修复是把耗时逻辑移出读线程。这个案例提醒:Recv-Q 持续堆积是「应用没读」而不是「网络慢」的直接信号。
上一页: 连接失败与建立缓慢案例下一页: 连接泄漏与状态异常案例返回: 网络性能分析与故障排查