strace 跟不动的线上问题:抓 syscall 逐层定位方法

举报
yd_246468676 发表于 2026/11/06 21:03:39 2026/11/06
【摘要】 一、从进程卡死到 syscall 现场

一、从进程卡死到 syscall 现场

线上告警群里最常见的描述是"进程还在,但就是不干活了"。这时候第一反应往往是 strace -p,可真挂上去,屏幕上刷出来的可能是几十万行 futex、epoll_wait、clock_nanosleep 混在一起,Ctrl+C 都按不赢。Kernel 5.15 上实测,抓一个长连接网关进程 3 秒,输出 8 万多行,光靠肉眼翻根本找不出卡点。更麻烦的是 strace 本身会放大问题:每个 syscall 两次上下文切换,高并发进程被 ptrace 之后,耗时从 50ms 涨到 400ms,原本只是慢的接口直接超时,现场被观测者改写了。所以第一步不是抓,而是先缩小范围。用 cat /proc/12345/status 看 State,D 状态说明卡在 IO,S 加高 utime 说明在空转,再配合 /proc/12345/stack 和 wchan 拿到内核侧阻塞点,通常能直接落到某个文件系统或锁等待上。确认有 syscall 层面的悬念再上工具:strace -p 12345 -T -tt -e trace=network,desc -o /tmp/s.log,只留文件描述符和网络两类,退出时用 -c 拿汇总,看哪类调用占比和总耗时最不正常。比如一次线上排查里,write 只占调用数 2%,但累计耗时 11.6 秒,问题就直接指向某个 fd 的写缓冲满了。

二、高频调用与阻塞点的辨识

把 -c 汇总拿到手,第一件事是看分布而不是看绝对值。同样 3 秒采样,一个正常网关进程的 syscall 结构大致是 futex 和 epoll_wait 占大头,各自几十个百分点;一旦某个 fd 相关调用突然顶到前列,就该顺着数下去。常见误判是把高频当热点:futex 一秒几万次往往只是锁竞争的正常表现,真正拖住业务的是单次耗时长的调用。判断办法是给 strace 加 -T,每行末尾会打印该次 syscall 的内核耗时,正常 read/write 在百微秒级,超过 10ms 的就要单独记。更省事的是 -c -w,按 wall clock 统计而不是 CPU 时间,阻塞调用会自己浮上来。实测一个卡住的消费进程,recvfrom 调用数只占 3.1%,但 -w 下累计 wall 耗时 27.4 秒,平均每次 1.8 秒,对照 /proc/12345/fd 发现它读的是一个没人写的 socket pair,阻塞点就此锁定。再往下要区分是等锁、等 IO 还是等网络:epoll_wait 返回后紧跟的 read 若报 EAGAIN 说明是空转轮询,若长时间停在 read 上则是对端不吐数据,用 ss -tnp 看该 fd 的 Recv-Q 是否为零即可确认。必要时上 perf trace -p 12345,它对高并发进程的放大比 strace 小一个量级,5.15 内核上采样同样 3 秒只引入约 15% 额外开销。

三、落到源码级的最小复现

定位到具体 syscall 之后别急着改线上配置,先在本地把那一行复现出来。回到上面那个消费进程的例子,拿到阻塞 fd 的 inode,用 ls -l /proc/12345/fd | grep socket 对出 socket:[4026531841],记下这个号。然后在测试机上写一段最小代码,只保留出事那次调用的形状:一个 socketpair、一端只写不读、另一端按线上同样的缓冲大小 212992 去读。跑起来用 strace -T -e trace=recvfrom,sendto,write ./repro 盯住,正常情况下 recvfrom 每次都在 80 微秒内返回,一旦对端停写,第一行超过 10ms 的 recvfrom 就会跳出来,跟线上 -T 日志里的 1800 毫秒量级对得上,说明形状对了。再把缓冲调到实际值验证边界:内核 net.core.wmem_default 默认 212992 字节,写完这个量对端不读,sendto 立刻返回 EAGAIN,报错原文是 Resource temporarily unavailable,这就复刻了“没人写的 socket pair”。复现出来后缩到二十行以内,去掉业务逻辑,只留 socketpair 加两次循环,然后逐个变量往回拧:缓冲大小、读写方是否阻塞、是否有 O_NONBLOCK,一次只动一个,看哪一个改回去阻塞就消失。等最小例子里 recvfrom 的耗时从 1800 毫秒掉回微秒级,根因就钉死在这一行的语义上了,再回线上改才有依据。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。