这个坑值得记一笔。接口压测到六千 QPS 就压不动,CPU 九成但用户态只占四成,pidstat 显示上下文切换每秒四十万次,日志里没有任何报错,不知道卡在哪一层。

刚开始盯着「短连接反复建连,内核协议栈开销占了大头」,折腾了半个多小时,排掉了。

排查方向其实有限,先把可能性排一排。锁竞争激烈,大量时间花在 futex 自旋上;日志同步刷盘,每个请求都在等 fsync 返回;定时器精度设得太高,频繁唤醒抢 CPU。

动手时先分清用户态和内核态的比例

pidstat -u -w 1 10

采一份热点函数排行看调用栈

perf top -p $(pgrep -f app) -g

接着抓三十秒生成火焰图样本

perf record -F 99 -p $(pgrep -f app) -g -- sleep 30

等前面都确认过,再核对日志是否每条都在同步刷盘

strace -fc -p $(pgrep -f app) -e trace=write,fsync

怎么算真的好了,看的是同一批现象。关掉同步日志并把连接改成复用后,上下文切换降到每秒五万次以内,同样 CPU 下 QPS 提升到一万二。

容易忽略的是,内核态占比高时别急着换语言或者加机器,先看系统调用的分布;strace 的汇总输出往往一眼就能看出哪类调用在拖时间。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。

作者 9823189