目标
没有退避的三次立即重试等于把 4 倍流量精准砸向一个正在挣扎的依赖。tcpdump 能在数据包层面让这种放大现形:依赖劣化的那几十秒里,成片的 SYN 与重传全部来自你自己的客户端。本食谱通过抓包计数与应用重试日志互相印证,证明重试风暴确实存在,并用带抖动的退避修复后再次抓包验证。
步骤要点
- 用 tcpdump 过滤指向依赖 IP 的纯 SYN 包并计数,健康期应接近零,事件窗口内激增即说明存在连接抖动。
- 用 tcp-retransmission 过滤器抓 30 秒重传,按源端口统计,判断是同一批连接反复重传还是新连接在失败。
- 在应用日志里统计 attempt=2、attempt=3 的条目,取出时间戳与退避值,与抓包时间线对齐,backoff=0 加数据包尖峰即坐实无等待重试。
- 给客户端加上指数退避加 30% 随机抖动的重试封装,只重试幂等操作,并在同样的劣化窗口重新抓包验证流量被摊开而不是集中爆发。
排错提示
抓不到包多半是流量走了别的网卡或 sidecar,先 ip addr 列接口改抓 sidecar 端口;重传过滤器没命中但应用仍异常,可能是依赖能握手却响应慢,改抓载荷测响应间隔;容器里没权限就用节点级抓包按 Pod IP 过滤,节点层能看到全部 Pod 流量。
适用边界
抓包只展示行为不解释意图,必须配合重试计数才能把流量归因到具体客户端代码;高流量下长时间抓包会产生巨大文件,务必用 timeout 或包数上限约束。
代码示例
# Count fresh connections to the dependency over 30s
sudo timeout 30 tcpdump -i eth0 -nn \
'tcp[tcpflags] & tcp-syn != 0 and dst host 10.0.4.12' 2>/dev/null \
| grep -c "S" # healthy: ~2/min, storm window: 900+/30s
# Same window after adding jittered backoff: ~5/min