不知道你有没有这种经历:半夜被一条"系统负载飙高、服务无响应"的告警吵醒,登陆上去一看,uptime显示的负载高得吓人,可top里每个进程的CPU占用看起来都低得离谱。内存还剩不少,业务却一个接一个超时。你本能地想去重启服务、重启机器,甚至申请扩容,但第二天它又好了,第三天又犯,始终说不清根子在哪里。
我做了很多年Linux性能排查的活,从"系统慢"这种模糊反馈到最终精准定位到某个进程、某行代码,中间走过的弯路比直路多得多。后来我慢慢摸到一套固定的排查秩序:先看整体、再按CPU/内存/磁盘/网络四个维度逐个排掉,最后才轮到进程级、系统调用级和内核日志级。这套流程不依赖玄学,也不用一次性记住几十个参数,只要把三板斧用好,绝大多数"系统慢"都能在几十分钟内收敛到明确的根因。
这篇文章我就把这套流程完整讲一遍。没有花哨的工具,全是标准发行版自带的命令,适合做运维、搞后端开发的你直接照着抄,也适合刚接触Linux性能问题的朋友建立自己的排查框架。准备好终端和一颗不慌的心,我们从最基础的三条命令开始。
1. 先摸清排障思路:从"系统慢"到"哪里慢"
1.1 五分钟建立整体秩序:先横向判断,再纵向深挖
接到"系统慢"的第一反应不要是"重启一下",而是先问三个问题:慢的规模有多大?是全站所有接口都慢,还是只有某个服务慢?是持续变慢,还是周期性抖动?这三个问题的答案决定了下面排查的走向,也决定了你该从哪一层下手。
我习惯把性能问题分成两类。第一类是资源耗尽型:CPU算力不够、内存不足、磁盘IO饱和、网络带宽被打满,这类问题指标特征非常明显,用top、vmstat、iostat、ss对着看很快就能找到。第二类是业务代码或架构问题:锁竞争、线程池耗尽、连接泄漏、慢SQL、调用链路上某个下游超时,这类问题往往资源看起来还过得去,但延迟已经高到不可接受,需要深入进程内部去看。
排障的通用节奏是先横向、再纵向。横向是指用uptime看负载、用top看整体资源占比、用vmstat看每秒快照,先确定瓶颈在哪个资源维度。纵向是确定维度之后,再递进到具体的磁盘设备、具体网卡、具体进程、具体线程、具体系统调用,直到抓出元凶。整个过程就像剥洋葱,层次越往下,干预手段越轻,越靠近真因。
提示:排障现场最忌讳的是没有时间线概念。命令输出的时间戳、告警触发的时间点、业务开始异常的代码发布时间,这三者一对照,很多看似随机的问题其实都有规律。
1.2 读懂系统慢的三种典型表现
具体到一台Linux服务器上,"慢"通常只有三种外显形式,认清它们能帮你快速缩小范围。
第一种是CPU密集导致的服务响应慢。特征是top里us或sy列居高不下,进程自己的CPU占用经常打到接近核数上限,代码里通常有死循环、密集计算或频繁垃圾回收。第二种是IO密集导致的慢。特征非常独特:负载很高但CPU大部分在wa上等待,vmstat里b列(不可中断睡眠进程)持续不为零,应用日志里到处是超时。第三种是等待型慢,CPU和磁盘都没有明显瓶颈,但请求就是慢,常见原因是锁竞争、线程池排队、网络往返太高、下游依赖超时重试。这种最难排,因为表面数字都正常,必须靠链路追踪和进程内部观测来破案。
写这篇文章时我特意把注意点放在"现象→指标→命令"的对应关系上。你不需要背住每一个内核计数器,但一定要知道每种现象该看哪个指标、用哪条命令去量化它。
1.3 动手之前的必备准备
排障不是光靠命令硬拼就行的,动手前花两分钟准备,效率会高很多。
首先确认你的终端能保持长期连接而不被中断,screen或tmux是标配。其次确认有足够的权限,性能排查中dmesg、strace、perf这类命令动不动就要root权限,没有权限会走很多弯路。第三是把所有操作都记录到一个临时笔记里,包括时间点、看到的关键输出、执行过的命令。很多问题不是当场解决不了的,而是要复现、要对比,没有记录就失去了对比的基准。
还有一条虽然是常识但必须强调:在业务高峰期尽量少用top和vmstat这样的交互式命令长时间挂着,这些命令本身会消耗少量CPU,在濒临崩溃的机器上会造成额外的抖动。需要持续采集的时候,用top -bn1批量模式或vmstat 1 5等定时采样的方式更稳妥。
2. 第一板斧:三条命令完成全局粗筛
2.1 uptime与load average:负载数字到底在说什么
命令是uptime,输出长这样:
$ uptime 14:32:18 up 42 days, 4:11, 3 users, load average: 12.50, 9.80, 7.20末尾三个数字分别代表1分钟、5分钟、15分钟的平均负载。很多人第一次看到load average超过CPU核数就慌了,其实这个数字代表的是"处于可运行状态和不可中断睡眠状态的进程平均数量",它不是CPU占用率,也不是百分比。一个4核的机器,load average长期维持在4左右说明CPU刚好忙得过来,超过4就说明有进程在排队等待CPU了。
判断load average是否偏高,必须结合CPU核数和趋势。先看nproc拿到核数,再用load除以核数。以4核为例,load达到8到12时基本可以确认CPU饱和;但如果load高而CPU的idle又很高,情况就完全不同了——这就指向了不可中断睡眠进程,也就是D状态进程,常见于磁盘IO、NFS挂载、内核锁等待。我在后面的案例复盘里会详细展开这种"假高负载"。
还有一点:只看即时值没有意义,要看趋势。15分钟是5、1分钟飙到12,说明系统刚刚开始恶化,排查要抓后者的现场;如果三者都高,说明问题已经持续一段时间,可以先抓快照再去查历史指标。
2.2 top/htop:打开进程世界的第一窗口
top是查看全局的第一现场。注意几个关键区:顶部的load average、Tasks总数、%Cpu(s)这行里的us、sy、wa、hi、si,以及进程列表里的%CPU和%MEM。
我一般会按顺序做这几步操作:先按数字键1看一下每颗CPU的核心占用,确认是不是只有单核被逻辑打满;再按P按CPU排序、按M按内存排序,来回切换几次,看看是哪个进程一直在前面;最后按c展开完整命令行,确认这个进程对应哪个业务。排查期间的修改都不要保存退出时的配置,免得污染下次使用。
top默认刷新间隔是3秒,排障时可以手动按d改成1秒。需要把结果保留下来给别人看时,不要截图,直接用批量模式:
$ top -bn1 | head -30批量模式非常适合写成脚本或定时采集。还有个很有用的技巧:top -p 1234可以只看某个进程,配合-H参数能看到这个进程下所有线程的资源占用。线程级别的排查对Java、Go这类高并发应用极其重要。
2.3 vmstat:每秒快照里藏着瓶颈线索
哪怕top已经把问题指出来了,我还是会补一条vmstat,因为它能一次性提供CPU、内存、IO和上下文切换等多个维度的每秒快照,是纵向排查的"分岔路口"。
$ vmstat 1 5 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 2 14 1024000 345200 123456 7890123 100 200 500 3000 2000 2500 3 2 80 15 0用的时候只盯几列:r列是运行队列长度,持续大于核数说明CPU已经排队;b列是处于不可中断睡眠的进程数,持续不为零说明有进程卡在IO上;us/sy是用户态和内核态CPU占比,sy占比过高要怀疑系统调用频繁或内核异常;wa列是CPU等待IO的时间占比,高企不下基本可以确定磁盘这层出问题;si/so是换入换出内存,两个都不应为常值,出现持续换页说明内存真的不够用了。
vmstat 1 5的含义是每1秒采样一次,总共采样5次。命令执行完后看最后两三行的平均值比较有代表性,第一行往往是从开机以来的累计均值,参考价值不大。
3. 第二板斧:四个资源维度逐一定位
3.1 内存维度:free与dmesg组合判断
top里看到某个进程%MEM高不代表内存的问题一定要处理,真正要判断的是系统还剩多少可用内存。这个判断标准不是free字段,而是available字段。用free -h看输出:
$ free -h total used free shared buff/cache available Mem: 15Gi 8.1Gi 1.2Gi 212Mi 6.1Gi 6.3Gifree这列是真正没被任何东西占用的物理内存,buff/cache是内核用来缓存文件读写的,这部分在内存压力大的时候是可以回收的,所以一个正在正常运行的Linux系统里free看起来小并不代表危险。available把可回收的buff/cache也算进去,它才更接近"还能塞下多少新进程"的真实答案。
判断内存问题还有一个稳定路径:当available长期低于总内存的10%,并且vmstat里si/so开始出现非零值时,内存肯定是真不够了。此时看谁在吃内存,用ps aux --sort=-%mem | head -10,再配合dmesg -T | grep -i oom确认内核是否杀过进程。内存问题最怕的就是只看free数值——数值还剩一半,但换页已经把系统拖垮了,这种我见过太多次。
3.2 磁盘IO维度:iostat+pidstat+iotop三板斧
CPU和内存排完还没找到根因,八成是磁盘IO。第一命令永远是iostat -xm 1 3,-x输出扩展统计,-m用兆字节展示,每秒1次采样3轮:
Device r/s w/s rkB/s wkB/s rrqm/s wrqm/s %rrqm %wrqm r_await w_await aqu-sz rareq-sz wareq-sz %util vdb 100.0 800.0 5120.0 102400 0.0 1200.0 0.0 60.0 5.0 50.0 40.0 51.2 128.0 100.0看这组数据我固定只看四个值:%util接近100%说明设备已经很忙;w_await代表写请求平均等待时间,正常机械盘在十几毫秒以内,SSD应该在个位数,飙到几十毫秒就是性能恶化;aqu-sz是平均队列长度,持续大于磁盘并发能力说明请求在排队;rrqm/s和wrqm/s代表合并的请求数,这两个数值高说明应用在发出大量零散IO,感受一下就知道这是可以优化的方向。
有一个很多人踩过的坑,SSD的%util可能长期显示100%,但实际上延迟依然很低、设备并没有到瓶颈。这是因为%util统计的是采样周期内设备有IO请求在持有的时间比例,NVMe这类高并发设备在处理大量并行小请求时这个值天然很高。所以判断磁盘是不是真瓶颈,优先看await和窗口内是否出现应用超时,而不是死抠%util。
用iostat判断设备有压力之后,还要知道压力来自哪个进程。用pidstat -d 1能列出每个进程每秒的读写字节数和延迟,用iotop能实时看到进程的IO占用排序。这三板斧下来,基本就能定位出是数据库写日志、是备份脚本扫数据,还是某个应用的缓冲刷得太勤快。
3.3 网络维度:ss、sar和内核网络参数
很多"系统慢"的根因在网络层。但这里有个常见的误区:很多人习惯先ping,实际上ping只是ICMP通不通的验证,与TCP连接质量的关系有限,真正该看的是一眼连接状态和收发队列。
首选命令是ss,它是netstat在现代Linux里的替代品,输出快且信息量更大。使用ss -s看汇总:
$ ss -s Total: 1024 (kernel 2048) TCP: 512 (estab 256, closed 200, orphaned 56, synrecv 12, timewait 128)重点关注timewait和estab的比值。正常情况下timewait会存在但不会堆成灾,如果timewait占连接总数的比例明显偏高,同时业务反馈新连接建立慢,基本要考虑调整tcp_fin_timeout和是否开启tcp_tw_reuse。再看ss -lnt里监听端口的Recv-Q和Send-Q:Recv-Q持续堆积说明有连接进来了但应用没来得及accept,这是典型的线程池饥饿;Send-Q堆积说明对端收不过来了,要怀疑下游消费能力或带宽。
流量层面用sar -n DEV 1 3看网卡吞吐,用sar -n TCP 1 3看TCP新建连接数。带宽打满时rxkB/s或txkB/s会接近网卡上限,这时候再回头看具体是哪个进程在占用,可以用nethogs或lsof -i辅助定位。
3.4 CPU与进程维度:pidstat之后还有perf与strace
如果top中的进程CPU很高,问题到进程这层还不够,还要深入线程和系统调用。pidstat -u -r -d 1可以把CPU、内存、IO三个指标按进程打印出来,比反复切top的排序更稳当。想看线程级别,加-t参数即可。
确认一个进程在忙,但不知道它在忙什么的时候,perf top是效率极高的选项。它会周期性采样并给出热点函数名,一条命令就能看到"CPU时间到底烧在哪段代码里",省去了反复猜、反复加日志的痛苦。需要更深的火焰图时,用perf record -g -p 进程号采集一段时间,再perf report看调用栈。
如果是频繁系统调用导致的高sys占用,strace -c -p 进程号会统计一段时间内各系统调用的次数和耗时,Ctrl+C停止后输出汇总。看到futex、nanosleep、poll这类调用高频出现时,要往锁竞争、线程等待方向想;看到大量read、write,则要往IO方向想。这两个工具用好,已经足够穿透绝大多数CPU层面的疑难杂症。
4. 四个真实故障场景的完整复盘
4.1 场景一:load average飙到12,CPU却闲着
某次线上服务无响应,我登陆时看到的第一个异常是uptime输出load average接近12,但top里CPU的idle有80%以上。顺着"CPU不忙但负载高"这个矛盾,我执行了vmstat 1 3,结果b列稳定在14左右,几乎没有归零的趋势,同时bi列也在持续上涨。
b列是D状态进程,这种状态通常是进程在等待磁盘、内存交换或内核锁,外力很难干预,连kill都经常失效。我接着用iostat -x 1去扫所有块设备,发现某块数据盘的%util为100%、await接近100毫秒,磁盘明显已经处在"拒绝服务"状态。再用pidstat -d 1逐个进程看,找到那个一直往这块盘写数据压缩存档的后台任务,最终定位是它在反复读取一块已经出现坏道的分区。
处理方式是把存档任务的数据目录迁移到健康的另一块盘上,业务立刻恢复。这个场景教给我一个原则:load average高只是结果,vmstat的b列和iostat的await才是分诊依据,不要看到负载高就加机器,先把D状态的源头揪出来。
4.2 场景二:内存剩余很多却频繁OOM,available才是真相
另一个典型场景是服务进程偶发被内核杀掉,系统本身还算稳定,但查看监控发现内存一栏写着"还剩好几个GB",完全看不出问题。我当时的操作顺序是:用free -h确认available其实已经见底,而free字段看起来还有几个GB是因为buff/cache一直都在被回收、被占满、再回收的循环里。
接着我翻了dmesg -T的输出,看到一段典型的OOM记录,里面明确写着内核杀掉了一个进程,还标出了该进程的vss和rss。再配合ps aux --sort=-%mem看内存占用排序,发现是应用侧一个缓存组件把机器内存吃光了。当时业务代码里用本地内存做了大列表的缓存,没有设置上限,也没有配合过期清理,数据量一上来就不断争夺内存。
处理手段是给进程设置内存上限,并在应用侧把那个无上限的缓存加上淘汰策略,同时建议在监控里加一条available内存低于物理内存15%就报警的规则。从那以后我判断内存是否够用,永远先把available当第一指标,free只作为参考。
4.3 场景三:数据库响应变慢,磁盘IO饱和的连锁反应
一个面向用户的基础服务突然在高峰期出现大范围超时,数据库CPU占用只有20%,看起来没什么问题。但业务方反馈每一个SQL查询都比平时慢几倍,这就很反常——数据库CPU不高,慢就指向了其他地方。
我用iostat -x 1连续看了30秒,数据盘的w_await在峰值达到80毫秒,%util长时间100%。再用iotop确认占用IO的进程正是数据库实例本身。进一步看数据库慢日志,发现大量查询走了全表扫描,返回的行数也不大,但扫描的数据量巨大,导致频繁读取数据文件,把磁盘队列彻底拖垮。同时日志刷盘机制又把随机写叠加进来,读写两头同时压。
修复分两步:先在数据库里为高频查询补上合适的索引,让查询从全表扫描降到索引查找,读压力立即下降;再把redo日志目录移到单独的磁盘,把随机写从数据盘拆出去。改动上线后,磁盘await回落到了个位数。这个例子说明,磁盘瓶颈有时不是上层代码直接写盘,而是某个业务的查询模式间接导致的,排查时要顺着"谁在IO"这条线一路找到末端。
4.4 场景四:接口大量超时,TCP连接队列被塞满
还有一个让我印象深刻的场景:服务进程CPU、内存、磁盘全部正常,但接口就是大量超时。我补了ss -s后发现timewait的数量高得异常,紧接着看ss -lnt,发现业务端口上的Recv-Q持续有几百个连接积压。Recv-Q积压的意思很明确:TCP三次握手完成了,accept队列里排着队,但应用线程一直没有把它们取走处理。
方向瞬间从"系统资源"转向"应用处理能力"。查业务线程数后发现,这个服务的线程池被某个外部依赖的同步调用卡住了,线程全部阻塞在等待对方响应上,新请求进来没人处理,只能堆在内核队列里。根因是下游接口在高峰期响应变慢,而线上服务对下游没有配置超时熔断,一个下游慢拖垮了整个上游。
处理时先给这个服务的线程池扩容到原来的两倍,临时扛过峰值;随后在代码里给下游调用设置了超时时间,并加了快速失败逻辑,避免线程被无谓占满。线路全部加固之后再压测,接口超时基本消失。这个case让我养成了习惯:看到TCP连接堆积,先看Recv-Q和Send-Q,再往应用线程池和下游依赖排查,而不是单纯调内核参数。
5. 工具选型、速查表与一条命令抓现场
5.1 工具横向对比:什么场景用哪个
很多新手被一堆命令搞得头晕,核心原因是没有把工具和场景对上。我整理了一张常用选型表,排查时对着挑就行。
| 排查维度 | 首选工具 | 补充工具 | 核心关注指标 | 适用场景 |
|---|---|---|---|---|
| 全局总览 | uptime | top | load average、idle/wa | 刚接手时的第一眼 |
| CPU/任务队列 | vmstat | mpstat | r、b、us、sy、wa | 判断CPU还是IO瓶颈 |
| 内存 | free | ps、dmesg | available、si/so、OOM记录 | 排查内存不足与OOM |
| 磁盘IO | iostat | pidstat -d、iotop | %util、await、队列长度 | 定位磁盘饱和与IO源 |
| 网络连接 | ss | sar -n TCP | timewait、Recv-Q、Send-Q | 连接堆积与队列堵塞 |
| 进程耗时下钻 | perf | strace | 热点函数、系统调用分布 | CPU高但进程内难定位 |
| 长时间趋势 | sar | 监控系统 | 历史指标回放 | 排查结束后做基线对比 |
选型的逻辑很简单:先全局后局部,先系统后进程,先指标后数据。不要一上来就perf record,那是在还没确认问题方向时最容易浪费时间的方式。
5.2 一条命令抓取排障现场快照
复盘做的多之后,我把最常用的采集命令做成了一个别名,一条命令执行完就能拿到整个系统的"现场快照",非常适合故障当前时刻快速留下证据。建议你在自己的机器上也配一个:
alias sysdark='uptime; echo ---; vmstat 1 3; echo ---; free -h; echo ---; iostat -xm 1 3; echo ---; pidstat -u -r -d 1 3; echo ---; ss -s; echo ---; dmesg -T 2>/dev/null | tail -20'执行顺序有讲究:uptime看整体趋势,vmstat得到CPU和IO的分诊依据,free -h确认内存,iostat把IO落到设备,pidstat把设备落到进程,ss -s看网络连接,最后用dmesg检查内核有没有吐OOM之类的关键日志。这套快照拿到手,问题的方向一般就已经收敛到两三个候选了,接下来只需要针对其中一个做更深入的观测。
注意:
dmesg在很多系统上需要root权限,普通用户执行会直接报错。如果你是非root环境,把这段去掉,换用journalctl -k --since "10 minutes ago"的方式也能看到内核日志。
5.3 排障命里的避坑清单
基于上面的实战复盘,我把最容易误判的几个点集中列一下,你排查时对照使用。
load average高不一定是CPU忙,先看vmstat的b列和wa列,D状态进程和IO等待同样会让负载暴涨;free小不代表内存不够,available才是真相,buff/cache是内核的弹性资源;iostat的%util对SSD要谨慎解读,同时注意await才是延迟的直接体现;看到进程CPU占用低不要急着排除它,top默认显示的是采样周期内的平均值,瞬时高峰可能被平摊掉,要看更短周期的采样或配合pidstat做多次采样。
网络排查时,ping通了也不等于TCP没问题,ss -lnt的Recv-Q才能反映应用接受连接的速度。还有一条老生常谈但不能不提:排查前顺手把所有命令的版本确认一遍,不同发行版之间iostat、sar的输出列名略有差异,按上面这些关键字找列即可,不要死记列的位置。
6. 从救火到防火:性能基线养成记录
6.1 我的十条排障心得
经验这个东西,说再多不如自己踩一次。我把这些年排障最值钱的十条心得写在这里,每一条都是真金白银换来的。
第一,接到"系统慢"先忍住不登录生产环境瞎搞,先在监控平台上把最近半小时的趋势抓一遍,知道是从什么时候开始的,比知道现在多严重更重要。第二,所有命令都要加时间戳输出或手动记录,复盘时会发现很多当时没注意的细节。第三,优先怀疑"最近变了什么"而不是"哪里看起来不正常",代码发布、配置变更、数据量增长、上游依赖抖动,这四个因素覆盖了大多数故障诱因。第四,用top按CPU排序看不到问题就按内存排序,两个方向都没有才考虑IO和网络,这是成本最低的排除路径。第五,不要在一个可能没问题的维度上反复磨,iostat看过两轮没有异常就果断换方向,时间要花在刀刃上。
第六,D状态进程不是能随便kill的,它卡在不可中断的内核路径上,杀掉进程的前提是先解决让它卡住的外部资源,否则进程状态无法被清理。第七,OOM记录里写明的进程名字和内存占用是最高效的线索,先信内核日志再信应用猜测。第八,strace不要直接挂到高并发进程上跑超过几十秒,它会让目标进程变慢一个数量级,严重时直接引发雪崩,务必在低峰期或灰度环境操作。第九,任何性能问题都要留下证据链,命令输出、时间点、改动列表三者缺一不可,否则复盘根本没法往下走。第十,绝大多数问题都不是单一因素,而是资源临界时被一个触发点引爆,所以解决完主因之后,一定要顺手看看其他资源是否也接近阈值。
6.2 最容易翻车的三个误判
第一个误判是"上下文切换高=性能差"。上下文切换多本身不代表有问题,高并发的服务每秒几十万次切换是正常的,关键要区分是自愿切换还是非自愿切换。非自愿切换持续飙升才说明CPU核数不够、线程在抢时间片。vmstat里的cs只给出总量,想看更细的要用pidstat -w查看进程级别的自愿和非自愿切换次数。
第二个误判是"磁盘%util=100就是瓶颈"。前面提过SSD的并发特性会让这个指标失真,真正的判断要结合await、队列深度和应用侧延迟。有些高性能SSD在%util持续100时吞吐依然稳定,不需要人为纠结。
第三个误判是"看到TIME_WAIT多就急着调内核参数"。TIME_WAIT多通常只是表面现象,根因在应用频繁创建短连接,没有复用连接池。把tcp_tw_reuse改大只是掩盖症状,真正的修复是让应用层做连接复用。我见过太多团队把内核参数调得面目全非,问题反而更严重,最后还是回到代码层面才解决。记住,内核参数的调整要服务于应用行为,不要本末倒置。
6.3 建立基线与常态化观测
排查完一个问题,最高价值的动作是把这个问题的"正常水平"记录成基线,而不是满足于"今天恢复了"。没有基线,下次再出问题时你依然无法判断当前数值是健康还是危险。我在每套环境稳定运行一周后,会执行一次完整的sysdark快照,把load average、空闲内存、磁盘await、TCP连接数等核心指标保存下来,标记为"该环境的基准值"。之后每次排障,都拿现场值和基准值对比,偏离幅度一目了然。
日常观测依赖sysstat定时采集的sa历史记录,它默认每10分钟采集一次,也可以改成1分钟。这些历史数据在问题结束后仍然可以通过sar -q、sar -r、sar -d回放,让你在"现场已经恢复、找不到证据"的时候依然能定位,是非常划算的投入。再进一步,把这些采集指标接入统一的监控和告警体系,配上"可用内存低于阈值"、"磁盘await超过基线两倍"这类告警规则,很多问题在用户感知到之前就能提前处理掉。
做性能排查这么多年,我自己最大的心得是:不要迷信复杂的工具和花哨的图表,大多数"系统慢"问题的答案,就藏在那几条基础命令的输出组合里。把uptime、vmstat、iostat、ss当成你的体温计、血压计、血氧仪,熟练到能一眼看出异常,再配合perf和strace做精准下钻,你就能在别人还在猜的时候,稳稳地把根因抓在手里。最后一句话送给你:排障的本质不是看更多指标,而是快速排除正确路径之外的干扰,先救火,再复盘,最后把每一次救火都变成下一次防火的养料。