背景
干了 10 年网络,最常被拉进「P99 突然从 20ms 飙到 300ms」的排查群,然后第一句话永远是:「网络你们看下有没有问题。」
问题是——「网络有没有问题」这件事,在微服务架构里根本没有一个干净的度量。
TCP 没断、ping 通、丢包率 0.01%,但 TCP retrans 从 0 涨到 0.5%、conntrack drop 出现 3 次、某台宿主机 CFS throttle 把网卡 softirq 饿了一拍——这些在应用层看就是「RT 高」,在运维层看就是「网络抖动」。锅到底是谁的?
常见做法与分歧
我观察到团队里大致有 5 种应对方式,各有硬伤:
- 看 TCP retrans / conntrack drop:
nstat -az或ss -ti抓 retrans,再配合conntrack -L看 drop。硬伤:retrans 是结果不是原因;而且 0.5% retrans 到底算不算「网络问题」,没有共识。 - 每跳加 trace header(X-Network-Latency / X-RTT):网关记 client→gateway、gateway→upstream 的耗时差。硬伤:加了一跳的序列化/反序列化开销,且只覆盖 HTTP,gRPC / Kafka / 内部 TCP 长连接根本不走这条路。
- 主动探测(synthetic TCP connect / HTTP ping):每 5s 探一次。硬伤:探测路径 ≠ 真实流量路径(不同宿主机、不同队列、不同拥塞窗口),「探测正常」不代表「业务流量正常」。
- eBPF / tcptop / bpftrace:能拿到真实的 per-socket RTT、retrans、softirq 延迟。硬伤:学习曲线陡,需要内核 ≥4.18 + 权限,很多团队没有这个基建。
- 「网络没断就是应用的问题」:最省事,也最不公平。网络层 2ms 的 softirq 抖动,叠加应用侧 GC 10ms,总 RT 从 15ms 到 27ms——这锅算谁的?
我的倾向
我倾向分层归因模型,核心公式:
client-observed-RT
= app-processing-time(服务端 access log 的 upstream_response_time)
+ network-rtt(client 侧 connect + write + read 的差值)
+ queueing-delay(网关 / LB 排队,如果有的话)
具体做法:
- 应用层:access log 必须记
request_time - upstream_response_time,这个差值就是「网络 + 排队」。 - 网络层:在宿主机上跑一个轻量 eBPF probe(我用的 bpftrace,约 80 行),抓 per-socket
tcp_retrans,tcp_rtt,tcp_rttvar,按 5s 窗口聚合推 Prometheus。 - 判据:如果
request_time - upstream_response_time的 P99 突增,同时 eBPF 看到tcp_retrans或tcp_rtt突增 → 网络/宿主机侧问题;如果只有request_time涨、upstream_response_time也涨 → 应用侧问题。
这个模型不完美(eBPF 有开销、access log 精度受 NTP 影响),但至少把「网络锅 vs 应用锅」从玄学变成了可对比的两个数字。
想听大家
- 你们团队 P99 抖动时,第一反应是看哪个指标?有没有一个「30 秒内能判定锅在哪」的 shortcut?
- 上面 5 种做法,你实际用过哪几种?效果如何?有没有第 6 种我没提到的?
- eBPF 那条路,你们有没有更轻量的替代(比如
ss -ti+ cron 采集)?精度够不够? - 最关键的:你们团队有没有一个「网络 vs 应用」的 SLA 分界线? 比如 retrans > 0.1% 算网络锅、> 0.5% 算事故?还是完全没有这个共识?
欢迎贴你们的具体做法、指标名、告警阈值,越具体越好。
0赞
0收藏
0楼层