延迟测量工具:一把尺子量到底

说实话,做延迟优化,最怕的是“我感觉”。

我感觉是网络慢,我感觉是数据库瓶颈,我感觉是代码写得烂——这些都是猜测。我个人的习惯是,不管遇到什么问题,先拿工具量一量。没有数据,就没有发言权。

这一章,我就带你过一遍我最常用的几个测量工具。它们就像手术刀,能帮你精准定位延迟到底卡在哪一环。

基础网络延迟测量:ping & curl

ping——最基础的探针

ping 测量的是网络层的往返时间。它发一个 ICMP 包,等对方回一个,就这么简单。

我在项目里遇到过好几次,业务方抱怨接口慢,结果一 ping,发现丢包率 30%,延迟飙到 500ms——这根本不是应用层的问题,是机房网络链路在抽风。直接找网络运维换路由,问题秒解。

实战用法:别只 ping 一次。加个 -c 100,连续发 100 个包,看最小、最大、平均延迟和丢包率。
# 连续 ping 100 次,统计延迟分布
ping -c 100 target.com

# 只看结果摘要
ping -c 100 -q target.com

curl——应用层延迟探测

ping 测的是网络层,但很多时候问题出在应用协议上。这时候我习惯用 curl。

curl 有几个参数特别好用:-w 可以输出自定义的时间指标。我经常用这个来快速判断“是网络慢还是服务端处理慢”。

# 输出 curl 各阶段耗时
curl -o /dev/null -s -w "\\nHTTP 状态码: %{http_code}\\n"
curl -o /dev/null -s -w "DNS 解析: %{time_namelookup}s\\n"
curl -o /dev/null -s -w "TCP 连接: %{time_connect}s\\n"
curl -o /dev/null -s -w "TLS 握手: %{time_appconnect}s\\n"
curl -o /dev/null -s -w "首字节: %{time_starttransfer}s\\n"
curl -o /dev/null -s -w "总耗时: %{time_total}s\\n"
curl -o /dev/null -s -w "下载速度: %{speed_download}B/s\\n" \
  https://api.example.com/health
关键判断:如果 time_starttransfer 远大于 time_connect,说明服务端处理慢;如果 time_connect 本身很高,说明网络连接不稳定。

压测工具:wrk & ab

wrk——现代化的 HTTP 压测

wrk 是我目前最常用的压测工具。它基于 epoll/kqueue,能轻松打出几万并发。

说白了,它比 ab 更轻量,结果也更真实。我记得有一次做网关优化,用 wrk 压测才发现了连接池泄漏的问题——从第 5 秒开始,延迟曲线直接起飞。

# 基本用法:4 线程,100 连接,压 30 秒
wrk -t4 -c100 -d30s https://api.example.com

# 带自定义脚本压测 POST 接口
wrk -t4 -c200 -d60s -s post.lua https://api.example.com/submit

ab——经典的 Apache 压测

ab 是老牌工具了,胜在简单。虽然单机并发能力不如 wrk,但胜在随处可见。

我个人的习惯是:快速验证用 ab,长时间压测用 wrk。

# 100 个请求,并发 10
ab -n 100 -c 10 https://api.example.com/

# 带 Keep-Alive 压测
ab -k -n 1000 -c 50 https://api.example.com/
维度 wrk ab
并发模型epoll/kqueue(事件驱动)多线程 + select
单机并发上限10 万+ 连接几千连接
支持自定义脚本✅ Lua 脚本❌ 不支持
结果详细度中等较高(含时间分布)
快速验证场景✅ 推荐✅ 可用
长时间压测✅ 推荐❌ 不推荐

系统级分析:perf & strace

perf——内核级采样器

perf 能深入到 CPU 指令级和内核栈。

嗯,这里要注意:perf 的数据量非常大。我一般先录 30 秒,然后看热点,而不是全量分析。

# 记录 30 秒 CPU 事件
perf record -g -F 99 -p PID -- sleep 30

# 生成火焰图数据
perf script > out.perf

# 用 FlameGraph 工具生成 SVG
stackcollapse-perf.pl out.perf | flamegraph.pl > flame.svg

为什么用 -F 99?因为 99Hz 采样率足够捕捉异常,又不会产生太多数据。我在定位一个 Redis 高延迟问题时,就是用 perf 发现 Redis 的内核态 spinlock 占了 40% 的 CPU——那是内核版本的一个 bug。

strace——系统调用侦探

strace 是跟踪进程和内核交互的利器。每次 read/write/connect 都能看到。

重要:strace 有臭名昭著的“慢镜效应”——被跟踪的进程会慢 10-100 倍。千万不要在线上直接 strace,除非你想被同事“请吃饭”。
# 跟踪系统调用,统计耗时
strace -c -p PID

# 只看网络相关调用
strace -e network -T -p PID

# 跟踪子进程
strace -f -e trace=network -T -p PID

我曾经用 strace 抓到一个诡异问题:每次请求都会莫名其妙多等 300ms。结果发现是应用层在每次请求前做了一次 DNS 反向解析——上游 DNS 超时了。这种问题,不用 strace 根本就发现不了。

测量工具全景图

为什么需要这么多工具?因为它们分别覆盖了不同的层级。我画了一张图帮你梳理一下:

延迟测量工具全景图 网络层(Layer 3/4) 测量目标:网络往返时间(RTT)、丢包率、路由跳数 推荐工具:ping、traceroute 应用层(Layer 7) 测量目标:DNS解析、TCP连接、TLS握手、首字节时间 推荐工具:curl -w、ncat、openssl s_client 压力测试层 测量目标:吞吐量(RPS/TPS)、P99延迟、并发连接数 推荐工具:wrk、ab、hey 系统内核层 测量目标:系统调用耗时、CPU热点、锁竞争、内存分配 推荐工具:perf、strace、ftrace、bpftrace

什么时候该用哪个?

我总结了几个典型的诊断场景,你可以照着来:

  1. 用户说“页面打不开”:先 ping,排除网络不通;再 curl -w,看哪一步卡住了。
  2. 接口响应忽快忽慢:上 wrk 压测,看 P99 延迟是否有抖动。如果有,说明服务端有资源争抢或 GC 问题。
  3. CPU 飙升但业务量不大:用 perf 采样,看热点在哪里。
  4. 某次请求特别慢:strace 抓一次完整请求的系统调用链。
工作流建议:先外后内,先网络后应用,最后才上系统内核工具。别一上来就 perf,不然数据量能把你淹死。

避坑指南

我曾经犯过的错:在线上直接 strace -p PID,结果那个进程慢到超时,被健康检查踢掉了。血的教训——strace 一定要在预发布环境或低峰期用。

还有一点:压测工具的结果不要只看平均值。平均值会骗人。你看 ab 的结果,它默认会给出“90% 的请求在多少 ms 内完成”——这个比平均值更有参考价值。