慢调用为什么要三件套
分布式系统里一次慢请求涉及多个服务与多次网络往返,单靠任何一件工具都容易得出片面结论:调用链追踪能指出哪个环节的跨度耗时长,日志能把上下文与参数串起来,抓包能验证那段时间网络上究竟发生了什么。三者放在同一条时间轴上互相印证,才能回答「是本服务处理慢、还是下游慢、还是网络慢」这个看似简单却经常扯皮的问题。
基本信息
| 适用场景 | 微服务或跨系统调用中出现偶发或持续的慢请求 |
|---|---|
| 前置条件 | 各服务时钟同步(NTP),否则跨度耗时无法横向比较 |
| 关联键 | 追踪标识、日志上下文、五元组三类信息至少具备其一 |
| 无埋点时的替代 | 用时间窗加客户端地址加请求路径做近似关联 |
| 判定原则 | 应用处理耗时与网络往返耗时必须在同一时间轴上区分 |
典型使用场景
- 接口 P99 突然上升:先看链路追踪定位到具体环节,再决定深挖方向
- 下游服务互相指认:用抓包确认报文发出与返回的真实时刻
- 偶发超时无法复现:长期抓包加日志留存,等下一次出现时取证据
- 优化后回归验收:对比同一接口在改动前后的分段耗时
- 排查连接池或锁等待:把等待时间与网络时间分开统计
三件套联动
三件套联动
# 1) 追踪:按 trace_id 查 span 耗时(示意,具体查询取决于所用系统)
# 2) 日志串联上下文:
grep -h 'trace_id=9f3a' /var/log/app/*.log | sort | head -40
# 3) 抓包核对对应时间窗的下游交互:
tshark -r /tmp/cap.pcap -Y 'ip.addr == 10.0.0.8 && tcp.port == 3306' -T fields -e frame.time_relative -e tcp.len | head -20
# 4) 对齐三方时间轴前先确认时钟:
chronyc tracking | head -3耗时归属判读
| 证据表现 | 归属 | 下一步 |
|---|---|---|
| 应用跨度耗时长、下游跨度正常 | 本服务代码、SQL 或锁等待 | 看慢查询、线程栈与锁竞争 |
| 下游跨度耗时长、报文往返正常 | 下游服务自身处理慢 | 转到下游服务的日志与线程 |
| 报文发出到响应的间隙明显偏长 | 网络或对端协议栈 | 抓包看重传、窗口与握手 |
| 等待连接或线程的时间占比高 | 资源排队,而非网络 | 调整池大小或并发度 |
| 时间轴对不上、前后矛盾 | 时钟不同步或数据缺失 | 先校正时钟再重新取证 |
网络与应用的界限要在同一时间轴上判定:把追踪的时间窗、日志时间窗与抓包文件三者对齐后再下结论,避免各自用自己那套时间下判断。
缺少追踪能力时,先补最小可用埋点:在入口生成请求标识,透传到所有下游调用并写入日志,这一项改动的排障收益通常高于任何工具采购。