多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

Linux系统性能排查全攻略:从负载到根因的实战指南

Linux系统性能排查全攻略:从负载到根因的实战指南 接到“系统慢”的反馈别急着敲命令先搞清楚一件事慢是主观感受不是客观指标。同一个“慢”可能是办公网卡到页面打不开也可能是数据库机器CPU跑满导致查询超时还可能是某台存储服务器磁盘IO饱和拖累了整个集群。我在处理Linux性能问题时的习惯是先花两分钟跟业务方确认影响范围和时间窗口再按“全局负载 - 子系统瓶颈 - 进程定位 - 根因下钻”这条线一步步查下去。你手上这台机器如果连top都卡得敲不出来那说明问题已经很严重得换个思路处理。这篇文章就是来聊这件事的当有人告诉你“Linux系统很慢”你到底该怎么从模糊的体感出发用uptime、top、vmstat、iostat、pidstat、perf、strace这一票工具把问题一层层剥到最底层的根因。适合刚接触运维和Linux系统管理的新手也适合那些虽然会敲几个命令、但遇到复杂故障时不知道从哪下手的工程师。我会把排查思路、命令的判读方法、常见的坑和几个我真实处理过的案例都放进来尽量让你看完之后能直接照着上手。1. 内容整体设计与思路拆解1.1 性能排查的本质从现象倒推资源瓶颈Linux性能问题之所以让很多人觉得难是因为“系统慢”这个现象可以对应太多原因。就好比你说“车开着不得劲”可能是轮胎亏气可能是发动机缺缸也可能是变速箱打滑甚至只是油箱快空了。如果你不先做一轮系统性的检查而是直接凭感觉去查某个进程或某个日志大概率会在错误的方向上浪费几个小时。我自己的排查框架是固定的四步漏斗全局定性用uptime看负载用top看整体CPU和内存用vmstat 1看运行队列和阻塞进程。这一步的目的是确认瓶颈大概在哪个子系统是CPU、内存、磁盘还是网络。子系统定向根据第一步的怀疑方向用iostat看磁盘、用free和sar -r看内存、用ss或nicstat看网络。这一步是把“大概方向”收窄到“具体子系统”。进程定位用top或pidstat找出消耗资源最多的具体进程记录它的PID、CPU、内存、IO特征。根因下钻针对定位到的进程用perf看CPU热点函数用strace看系统调用用/proc/PID下的文件看线程和文件描述符最终搞清楚这个进程为什么消耗这么多资源。这套流程看起来简单但每一步都有不少细节。比如第一步里uptime显示的load average很多人都知道“超过CPU核数就危险”但这玩意儿到底怎么读、跟什么对比、什么情况下会误导你得说清楚。1.2 为什么用这些老牌命令而不是装监控系统现在监控产品很多Prometheus加Grafana一搭各种指标曲线看着很爽。但我的经验是生产环境出故障时监控系统可能没覆盖到这台机器或者覆盖了但指标采集频率太低又或者监控平台本身挂了。这时候你手上只有一台能敲命令的终端得靠Linux自带的这些命令撑住全场。更关键的是命令行工具给了你实时“现场感”。vmstat 1连续输出的每一行都在告诉你当前这一秒系统发生了什么pidstat -d 1能实时看到进程的读写速率变化。这种逐秒级别的观察能力是任何5秒或15秒粒度的监控都替代不了的。它们不是互相取代的关系而是互补监控系统负责事后回溯和趋势分析命令行工具负责故障时的现场定位。我还有个习惯排查时会把用到的命令和输出都记录下来时间戳精确到秒。一是方便事后写报告二是如果问题反复出现可以对比当时和现在的输出差异。这个习惯帮我解决过不少诡异问题后面细说。1.3 先建立一个重要的心理预期性能排查最怕的不是找不到根因而是找到的“根因”其实是另一个问题的表象。比如你查了半天发现是Java进程CPU跑满用jstack打了线程栈发现全卡在SocketInputStream.read上那问题根本不在CPU在IO或网络。如果你在“CPU跑满”这个层面就停下然后去优化代码里的计算逻辑方向就全错了。所以做性能排查脑子里要时刻有一根弦当前看到的瓶颈指标究竟是“根”还是“叶”。判断的方法不难——看这个指标背后的等待事件。CPU跑满要看是用户态计算占的还是内核态等待占的内存不足要看是应用堆占的还是页缓存被回收导致的磁盘忙要看是实际读写量大还是队列堆积。每一层都往下多问一个“为什么”基本上不会跑偏。这就是为什么我会在后面的篇幅里反复强调“不只盯着指标数值还要理解指标背后的语义”。2. 核心细节解析与实操要点2.1 全局负载判读uptime和top的正确打开方式接到“系统慢”反馈后我一般第一个敲的命令是uptime然后顺手敲top -c。前者看负载趋势后者看CPU、内存和进程快照。别看这两个命令简单很多人第一个判断就出错了。uptime输出中的load average有三个数值分别是1分钟、5分钟、15分钟的平均负载。这里的“负载”不是CPU使用率而是处于运行状态和不可中断睡眠状态的进程数之和的平均值。懂了这点你就明白为什么负载高不等于CPU忙——如果大量进程堵在磁盘IO上不可中断睡眠即D状态负载一样会飙升但CPU使用率可能很低。我判断负载是否异常的参照系是CPU逻辑核数。用nproc查看核数如果负载长期高于核数的70%-80%说明系统确实繁忙如果负载接近或超过核数说明有进程在排队等待CPU资源。但这里有个很容易误导新手的场景如果系统是128核负载长期在20左右看起来“很低”但某个进程已经把单个CPU核心打满了。uptime只看全局不看单核所以必须配合top里按CPU排序的进程列表来看。top的第一行会重复显示负载紧接着是进程和CPU状态统计。我重点看%Cpu(s)这行的几个值us用户态、sy内核态、waIO等待、id空闲、st被虚拟机偷走的时间。如果wa特别高基本可以确定磁盘在拖后腿如果sy特别高大概率是系统调用频繁或内核线程异常如果us特别高那一般是应用层计算密集。这几个值的正常比例没有绝对标准跟你跑的业务强相关但一旦某个值异常突出方向就清晰了。top里还有一个比较容易被忽略的指标load高但CPU闲、wa低这时候要怀疑内存回收或者进程数过多。进程数一多调度器开销就上去了系统看起来忙但真正干活的不多。这种场景我会直接敲ps -eLf | wc -l看线程总数如果好几万多半是应用线程泄漏。2.2 内存与虚拟内存free和vmstat里藏着的真相内存问题在Linux上有个普遍困惑free显示内存所剩无几是不是要挂了答案是否定的。Linux的内存策略是“闲着也是闲着不如拿去做页缓存”所以free里的available才是真正可以分配给新进程的内存大小而不是free列。我习惯看available这个数值是内核根据当前页缓存可回收性计算出来的比看free可靠得多。排查内存问题我通常用vmstat看两个东西si和soswap in/out。如果这两个数值持续非零说明物理内存确实不够用了系统正在把内存页换到磁盘上或者换回来。Swap的读写是磁盘操作性能比内存慢几个数量级一旦系统进入频繁换页的状态整体“卡顿感”会非常明显。这时候用free确认swap的使用量再用top按内存排序找出吃内存的进程基本能定位到元凶。有个容易被忽视的内存指标是vmstat输出中的cscontext switch上下文切换。如果这个数值每秒几十万次那说明系统在疯狂地切换进程或线程CPU大量时间花在切换现场而不是干活上。这种情况内存本身不见得不足更可能是线程数太多或锁竞争太严重。处理过Java高并发应用的同学应该有体会一个线程池开得过大、锁粒度太粗就能把CPU大量消耗在sy上而业务啥也没干。另一个内存相关的经典场景是OOM Killer。很多同学看到dmesg里有Out of memory: Kill process就慌了以为系统要崩溃。实际上这是内核在内存耗尽时的最后保护手段。排查时要搞清楚为什么内存耗尽通常用dmesg查看被杀进程的内存量再用free和top确认当前内存分配情况。如果反复出现就要考虑调大内存、限制进程内存使用或者排查应用是否存在内存泄漏。2.3 磁盘IO到底慢在哪iostat的每个字段都得会读磁盘IO问题最典型的特征是top里的wa值居高不下或者vmstat里的b阻塞进程数持续大于0。但要精准定位磁盘瓶颈还得靠iostat。iostat -x 1输出的字段比较多我最关注的是这几个%util设备的繁忙程度、await平均IO响应时间、svctm实际服务时间新版内核中意义不大可以忽略、w_await写响应时间、aqu-sz平均队列长度。%util接近100%说明设备已经满负荷运行但不等于“有问题”——如果IO响应时间很短只是请求量特别大那设备可能只是“忙但健康”如果await超过几十毫秒甚至上百毫秒说明设备确实响应迟钝可能连到的是慢盘、故障盘或者网络存储。判断IO问题还有一个容易被忽略的层面IO请求大小的分布。同样是一秒钟写100MB如果分成10000个10KB的小请求对磁盘的磨损和延迟远大于1000个100KB的大请求。这个信息从iostat里看不直接得配合blktrace或iostat -x里的rkB/s、wkB/s和r/s、w/s自行算一下。平均请求大小过小说明应用层有频繁的小块写操作常见原因包括数据库的大量随机小事务、日志文件的同步写等。关于IO排查有一个很容易踩的坑把“设备忙”等同于“性能差”。比如一个SSD的%util已经100%但await才1毫秒这时它只是被请求填满了性能其实很强。反过来一个机械盘%util只有30%但可能因为磁盘坏道导致await高达300毫秒。所以一定不要只看单一指标要把利用率、延迟、队列长度组合起来判断。2.4 网络层在性能故障中的角色有些系统慢根因在网络而不在主机本身。比如NFS挂载的目录IO慢、微服务调用超时、数据库连接被网络延迟拖垮表象可能在磁盘或应用层但流量路径一通排查才发现是交换机丢包或者网卡软中断过高。网络排查我常用的命令是ss -s看连接统计、sar -n DEV看网卡流量和错误包、ethtool -S eth0看网卡的错误计数、ifconfig看drop和overruns。如果发现网卡的rx_drop或tx_drop持续增长可能是环形缓冲区太小或者中断处理不过来。还有一个常见场景是网卡多队列没开启导致所有中断都打在同一个CPU上看top时某个CPU核心直接打满其他核空闲系统整体却反应迟钝。软件层面连接数耗尽也是一个高频故障。ss -s如果显示大量TIME_WAIT或CLOSE_WAIT得赶紧处理。TIME_WAIT太多可以调整内核参数net.ipv4.tcp_tw_reuse在出站连接场景下安全和tcp_fin_timeout来缓解CLOSE_WAIT堆积通常是应用没正确关闭连接表现为文件描述符泄漏得从应用代码层面解决。如果不分青红皂白地把tcp_tw_recycle打开可能会引入更诡异的NAT故障这个参数在新版内核中已经被移除了不建议用。2.5 性能排查工具速查表工具千千万我自己平时最常用的就那几个覆盖了绝大多数场景。下表是一个精简版速查方便你在排查时快速翻阅排查方向核心命令关键指标定位要点全局负载uptime、topload average、us/sy/wa/id负载与CPU核数的比值CPU热点top、perf top、pidstat单核使用率、用户态/内核态占比perf定位到具体函数内存压力free、vmstat、sar -ravailable、si/so、csswap换页频率、上下文切换磁盘IOiostat、pidstat -d、iotop%util、await、w/s延迟是否超过设备能力网络异常ss、sar -n DEV、ethtool连接数、drop、重传率单核软中断、连接耗尽进程级追踪pidstat、strace、perf单进程CPU、系统调用耗时strace聚合耗时perf看函数热点内存映射分析pmap、/proc/PID/smapsRSS、匿名内存、共享内存定位进程内存构成和泄漏趋势使用这些工具时建议用“专人专事”的方式做全局画像时用top和vmstat做定向分析时用pidstat和iostat做深度追踪时用perf和strace。没必要一上来就把所有工具都跑一遍那样除了刷屏没什么用。3. 实操过程与核心环节实现3.1 案例一Java应用CPU飙高如何从进程到线程再到代码之前处理过一个线上Java服务变慢的故障。uptime显示负载从平时的0.5飙到了8top -c看到有个Java进程CPU占用超过600%多核总计。因为Java是跨线程的直接看进程CPU占比没法知道是哪个线程在捣乱所以第一步是top -Hp PID按线程维度排序记下CPU占用最高的线程PID然后把它转成十六进制printf 0x%x\n 线程PID。拿到十六进制线程号之后用jstack PID导出线程栈grep一下这个十六进制号就能看到线程名和当前的调用栈。那次查出来的是GC线程一直在跑进一步用jstat -gcutil PID看GC统计发现Full GC非常频繁老年代一直回收不掉。症状其实是内存泄漏导致GC成为CPU消耗大户但如果不做“进程到线程再到栈”的下钻很可能还在业务代码里乱翻。在不能用jstack的场合比如没有JDK的权限或者进程不是Java用perf top -p PID也能看用户态热点函数。虽然看到的可能是匿名的JIT编译代码名字不够直观但配合perf record和perf report、再对照线程栈信息方向基本能定出来。这次实战教会我的一个教训是CPU飙高时别慌着优化代码先用线程栈确认热点在哪一层——业务线程、GC线程、还是内核线程三种情况解法完全不同。3.2 案例二磁盘利用率100%但系统不慢问题出在哪另一个经典案例是某台数据库备机iostat -x 1显示vda的%util持续100%但业务侧反馈没有明显变慢vmstat里的wa也不高。当时我的第一反应是“设备满负荷但不慢可能只是请求量大”。为了验证这个判断我检查了iostat的await和w_await发现写响应只有5-8毫秒对机械盘来说不算糟糕。再看w/s和wkB/s发现IOPS高达3000多但吞吐量只有几十MB/s典型的“小IO驱动高利用率”。随后我用pidstat -d 1找到了持续下发IO的进程是一个批量导出任务每次写4KB的块而且没有做批量合并。根因是应用层的一个初始参数设置不合理把写缓冲设得太小导致每个事务都触发一次独立的落盘。把参数调大后w/s直接降了一个数量级%util也掉到了30%以下。这个案例说明%util高只是结果真正的病因要看IO请求的模式。优化方向不是简单换更快的盘而是减少不必要的IO次数。3.3 案例三系统负载飙高但CPU空闲别让表象带偏你还有一种很容易误判的场景负载二三十top里CPU却大面积空闲us和sy都很低。这种组合通常指向D状态进程——它们阻塞在IO上不消耗CPU但会拉高负载。我用ps -eo pid,stat,comm | grep D过滤D状态进程发现一堆进程卡在xfsaild相关的写页缓存上。顺着查下去是底层存储设备因为控制器固件问题导致写延迟忽高忽低系统整体表现为“假忙”。在这个案例里vmstat中的b列阻塞进程数提供了另一个重要线索正常情况下这个值应该接近0但当时持续在20左右。对照iostat发现磁盘的await时而正常时而飙升到300ms一下就锁定到存储设备异常。之后联系存储厂商升级固件问题才彻底解决。这个教训是看到负载高先别急着加机器用vmstat的b列和ps的D状态进程确认一下是不是有“隐形”的IO阻塞方向对了才不至于白忙。3.4 用连续记录代替单次快照捕捉“幽灵”问题有时候性能问题是间歇性的——平时一切正常每天某个时段突然卡几分钟然后又自动恢复。单次敲命令往往抓不到现场这时候我常用老办法写个Shell后台脚本定时把uptime、vmstat、iostat、top的关键信息追加到文件里等故障时间段过去后回来看记录。脚本很简单大致长这样仅示意需按自己环境调整while true; do echo ---- $(date %F_%T) ---- /tmp/perf.log uptime /tmp/perf.log vmstat 1 3 /tmp/perf.log iostat -x 1 3 /tmp/perf.log ps -eo pid,ppid,stat,comm --sort-%cpu | head -20 /tmp/perf.log sleep 57 done这里有个细节脚本循环里vmstat 1 3本身会跑3秒加上sleep 57差不多每60秒记录一次分钟级快照。等到故障再现翻出对应线段的日志就能看到负载变化和进程趋势。这个方法不能替代实时排查但对于“幽灵般”的间歇故障往往是成本最低的抓取手段。我还踩过一个坑写脚本时没把pidstat的输出重定向导致大量数据直接打在终端上等想起来去看磁盘已经被日志塞满了。脚本里一定要用绝对路径输出到指定文件并且确保日志目录有足够的剩余空间。3.5 深度追踪的时机perf与strace要用在刀刃上perf和strace是性能排查的“外科手术刀”效果很好但代价不小。strace会接管进程的所有系统调用让目标进程变慢好几倍生产环境必须小心使用perf record会在内核里对采样事件做记录虽然一般影响不大但采样频率过高也可能加重负载。我的原则是前几层排查已经定位到具体进程之后才用它们去做根因确认绝不在刚开始时就上这些重武器。strace的正确用法之一是做系统调用耗时聚合。直接strace -p PID会刷屏根本看不过来我一般这样strace -f -p PID -c -o /tmp/strace_summary.txt # 让它统计15秒 sleep 15 kill $(pgrep -f strace -f -p PID) cat /tmp/strace_summary.txt-c参数会聚合输出每个系统调用的调用次数和总耗时。如果发现某个系统调用比如fsync、poll、recvfrom时间占比特别高那基本就是症结所在。这个方法的优点是不需要理解每一行输出只看聚合数据就能定位大方向而且对目标进程的干扰相对可控。perf则更适合CPU热点分析。perf top -p PID直接看实时热点函数perf record -p PID -g -- sleep 10抓10秒的调用栈数据然后perf report查看火焰图。CPU密集型的锁竞争、自旋等待、无效计算在perf report里都很显眼。我自己用下来感觉perf最擅长回答的问题是“CPU时间到底花在哪个函数上了”至于“为什么这个函数被频繁调用”还得配合业务代码、线程模型和调用链来分析。4. 常见问题与排查技巧实录4.1 场景一load average高但CPU利用率低该查什么这个问题出现的频率非常高。网上搜索的时候能看到大量相关讨论实际处理起来 按优先级排查 的思路大体如下先看是否存在D状态进程ps -eo stat,pid,wchan:32,comm | grep ^D。如果有一堆进程卡在D状态说明IO层有瓶颈可能是磁盘、网络文件系统或者是内核模块卡住了。看vmstat的b列是不是持续非零如果b持续大于0印证了上面有进程在阻塞。看iostat -x的await是不是异常升高如果是瓶颈基本就在存储设备上如果不是再考虑别的方向。排除操作系统层面的软中断问题top按si排序看有没有单核软中断打满可能跟网卡多队列、驱动异常有关。这套方法算是我自己的标准动作能避免在CPU利用率的迷宫里绕太久。之前有朋友遇到类似现象一直以为是CPU问题反复调cgroup限制结果问题根源在NFS服务端的网络延迟白白折腾了两天。4.2 场景二内存明明还有应用却开始swap有次排查一个内存问题free -h显示还有二十多G的available但vmstat里si和so就是不停地在跳。我当时也很疑惑物理内存这么充裕系统为什么要动用swap后来查了sysctl vm.swappiness发现这台机器被人改成了100。swappiness控制的是内核回收匿名内存页的积极程度数值越高系统越倾向于把不常访问的内存页换到swap而不是回收页缓存。对于很多应用来说这个值设为10左右就够用了除非你的业务负载非常特殊否则不建议改到100。另一个跟swap相关的坑是有些应用自己调用了mlock或使用了MAP_POPULATE导致部分内存页不可回收内核只能挑那些可回收的页去换。这种情况下应用的RSS很高但实际能回收的很少表现为“明明还有内存却一直swap”。检查方式是用cat /proc/PID/status看VmLocked字段确认是否有被锁定的内存区域。4.3 场景三进程CPU使用率忽高忽低如何确认真实利用率top里看到的CPU百分比是一个平均值term里会动来动去有时候看着某个进程CPU有时40%有时90%拿不准它到底吃多少。这时候用pidstat比top更靠谱因为它可以按固定间隔输出采样值不受终端刷新影响。pidstat -p PID 1 5这个命令每秒采样一次连续5次输出每次采样周期内该进程的CPU使用率。如果发现数值在某个区间内稳定波动那就是业务正常负载如果是规律性的“尖峰低谷”那多半有定时任务或周期性GC在作祟。pidstat还有一个好用的变体是pidstat -d 1可以看进程的IO读写速率配合iostat看设备整体状况能把“哪个进程在制造大量IO”这种问题很快锁定。4.4 场景四一条命令查看系统关键健康指标分享一个我日常用的“一条龙”命令算是快速健康检查uptime; free -h; vmstat 1 5; iostat -x 1 2; ss -s虽然只是把几个命令串起来但能让你在两分钟内对这台机器的负载、内存、CPU运行队列、磁盘IO和连接数有一个全局印象。这个操作适合作为故障排查的第一步也适合每天对重要机器做个例行巡检。我一般会再加一句dmesg -T | tail -20看看内核有没有报错比如IO错误、内存错误、进程被OOM杀掉等。内核日志里有些问题可能还没反映到业务层面早看到早处理。4.5 场景五排查经验如何沉淀成团队资产性能排查最大的浪费是同一个坑被不同的人反复踩。我习惯每次处理完一个性能故障都写一份简短的复盘记录包含时间、现象、排查命令和输出、根因、临时缓解措施、长期修复方案。哪怕只是几百字下次再遇到类似现象时翻出来一分钟就能对上号。表单可以做成这样时间现象定位思路根因临时方案长期方案2025-03-12应用响应变慢load升高uptime - top - pidstat - jstack连接池过小导致线程排队重启应用临时缓解调大连接池并加监控告警2025-04-08磁盘写放大%util高iostat - pidstat -d日志写入频率过高将日志级别调高引入异步日志组件2025-04-22负载高但CPU空闲ps D状态 - vmstat b列NFS服务端延迟切换存储路径更换为本地存储这份表格看似轻量但在团队协作中作用很大。新人来了照着表格里的案例实操一遍比看十篇理论文章都管用。而且这些记录过半年之后回头翻看能总结出一些共性的系统设计问题比如日志库选择不当、线程池参数拍脑袋、存储选型没评估IO模型。性能排查的终极目标不是每次救火成功而是通过一次次复盘把火种掐掉。5. 个人常用的排查心法5.1 先恢复服务再追根因这个话我说过很多次但每次都要强调生产环境出现性能问题最重要的是先止损。如果应用已经卡到不可用先重启、扩容或者切流让业务恢复再慢慢排查根因。不要为了“保留现场”而让故障持续恶化。保留现场的手段多的是top -b -n 1的输出保存下来vmstat记录存下来jstack打一份线程栈perf record抓一段数据/proc/PID/status里的内容复制一份。这些足够支撑事后分析。只要保存得当重启不会让根因消失反而因为业务恢复你可以更从容地做实验验证修复方案。有几次我为了追根因不许重启结果业务损失扩大最后被迫重启现场也没保住两头吃亏。5.2 用排除法缩小范围而不是大海捞针性能排查的核心是“分而治之”。把系统拆成计算、存储、网络三个维度逐一排查。更实用的做法是同时看两个维度找它们的交叉点。比如磁盘慢可能是存储硬件问题也可能是文件系统配置问题还可能是网络存储的链路问题甚至可能是应用频繁写导致缓存刷盘频繁。单看iostat看不到全貌要结合pidstat -d、top的wa、ss的连接状态来交叉验证。排除法还有一个好处就是减少“假线索”的干扰。有一次排查MySQL变慢iostat显示磁盘读取很高但仔细看pidstat -d发现高IO的进程不是MySQL而是备份脚本把备份任务暂停后数据库立刻恢复了。如果不做交叉验证你可能已经在给MySQL加索引或者调缓冲池了。5.3 内核参数与性能调优的边界很多文档会推荐一大堆内核参数设置比如vm.swappiness、net.core.somaxconn、fs.file-max、kernel.shmmax等等。我的态度是没有明确问题前不要盲目调整系统级参数。每个参数改动的背后都有取舍牵一发动全身。比如把vm.dirty_ratio调大写入性能可能变好但一旦触发强制回写系统卡顿会更严重。内核参数调优的正确步骤是先明确瓶颈再针对性调整然后做对照验证。比如确认是TIME_WAIT连接过多影响新建连接时再考虑tcp_tw_reuse和tcp_fin_timeout确认是文件句柄耗尽导致服务异常时再考虑调大fs.file-max和进程的ulimit限制。调整之前用sysctl -w做临时生效确认效果后再写进/etc/sysctl.conf。5.4 工具之外的经验敏感度排查的次数多了你会开始对某些“气味”特别敏感。比如看到负载飙高但CPU闲你会本能地去查IO阻塞看到%util高但await低你会想到小IO并发过多看到si和so持续跳动你会检查swappiness看到sy占用过高你会怀疑系统调用太频繁或线程数失控。这种敏感度不是天生就有的是在一次次案例中练出来的。我给别人培训时说性能排查像当侦探工具只是放大镜真正靠的是推理链条。你的每一个“为什么”都要有对应的命令输出佐证这样得出的结论才立得住。有一次我判断是SSD磨损导致读延迟增加有人问“你怎么确定的”我列出的证据是iostat的await偏高但w/s不高加上smartctl查出的媒体磨损指示量持续增长再配合内核日志里偶尔出现的IO错误三个线索叠加起来证据链就闭合了。6. 几个值得再深挖的方向6.1 理解Linux调度器与等待事件想真正把性能排查做深不能停留在工具层面要理解Linux内核的基本运作方式。比如调度器如何把CPU时间分配给各个任务为什么会出现“运行队列很长但CPU使用率不高”的现象load average里的不可中断睡眠状态到底代表什么。这些知识能帮你把工具输出和系统行为关联起来。我的经验是遇到复杂问题多看看/proc下各文件的内容再对照内核文档比看二手资料理解得更可靠。6.2 从性能问题延伸到容量规划一次性能排查解决的不只是当下故障还能为容量规划提供宝贵数据。比如你的应用高峰期CPU使用率已经到70%按照常规水位线就该准备扩容或者优化了。排查中收集到的负载指标、IO模式、内存增长趋势都可以作为容量规划的输入。我每处理一次事故都会顺手把这些数据转成一份简单的趋势记录作为后续容量评估的参考。6.3 性能排查与云原生环境的差异容器和Kubernetes环境下的性能排查思路跟传统裸机有一些区别。比如在容器里执行top看到的CPU使用率是宿主机的全局视角如果不做lxcfs或类似隔离很难直接看到容器自己的CPU占用、得配合cgroup的统计文件。还有一个常见问题是容器内执行free看到的内存是宿主机的不是容器限额的数值这时候要看/sys/fs/cgroup/memory下的memory.usage_in_bytes。云原生带来很多便利但也让性能问题的定位多了一层抽象排查前先确认你的观测点到底在哪个层级。6.4 复盘并持续更新自己的工具库命令行工具生态一直在演进比如btrace、bpftrace、eBPF这些新工具能提供更精细的观测能力但学习成本也不低。我的建议是先把传统工具用熟练再去接触新工具。工具只是手段排查思路才是核心竞争力。我到现在处理问题80%靠的还是top、vmstat、iostat、pidstat这几板斧只是偶尔遇到特别刁钻的问题时才会上bpftrace和perf。把基础工具练到条件反射的程度比囤一堆花哨工具要实在得多。回看这些年处理过的故障真正棘手的往往不是技术本身而是如何在混乱的现象里保持思路清晰。性能排查这活命令记不住可以查手册思路断了才是真麻烦。希望这篇文章里拆解的排查链路、案例和技巧能帮你下次面对“系统慢”时少一点无从下手多一分从容判断。最后提醒一句排查完之后记得把你用过的命令、看到的输出、最后得出的结论整理成文档这份记录的价值可能比排查本身还大。
返回列表