
你有没有遇到过这种情况Linux服务器用着用着突然变慢了业务方甩过来一句“系统慢”你登录上去敲个top看到load average爆炸式上涨但进程列表里又看不出是谁在搞鬼。CPU看着有富余内存也没爆磁盘好像也没异常可服务就是慢得离谱。这篇博文把我做Linux性能排查的完整思路、工具组合和踩坑经历都整理了出来从冷冰冰的系统指标一路拆到底层调用讲清楚如何从“系统慢”三个字精准定位到具体的进程、线程、甚至是某一行代码。内容适合刚接手Linux运维的新人也适合经常被“系统慢”折磨得焦头烂额的工程师你们都能从这里找到一套可以直接套用的排查路径。1. 先说思路把“慢”变成能查的东西1.1 慢是一种主观感受指标才是客观依据我见过不少人排查性能问题时上来就盯着top看三五秒然后拍板说“内存不够加内存吧”。这种操作很危险因为你把“感觉”当成了证据。系统慢可以来自CPU争抢、内存回收、磁盘I/O等待、网络延迟甚至内核锁竞争和进程D状态每个方向的处理方式天差地别。错误的判断不仅浪费资源还可能把原本健康的应用搞出更大的问题。我在排查时习惯先建立一套指标体系把“慢”翻译成四个大类CPU、内存、磁盘、网络。每一类又看三个维度利用率Utilization、饱和度Saturation、错误Errors。这套思路来自Brendan Gregg的USE方法论核心就一句话先发现系统层面的瓶颈再看是谁在占用资源最后深入代码或内核找出根因。你不一定要背这套理论但按照这个顺序走基本不会漏掉关键线索。实际操作中我会先跑一组基础命令把现场数据完整收集一遍uptime看负载趋势top看CPU和内存分布iostat看磁盘状态free看内存水位ss看连接情况。有人会问为什么不直接抓大进程因为系统慢往往是多因素叠加的结果比如内存吃紧导致swap频繁swap又引发I/O压力最后表现为CPU等待和业务卡顿。只看表层指标你永远找不到真正的病根。1.2 排查顺序与现场保护排了这么多年性能问题我最大的心得是接到“系统慢”这个反馈时第一件事不是解决问题而是保护现场。核心原则就两条不要急着重启服务不要乱kill进程。重启会把所有线索清零你只能等下一次故障再上演一遍。我建议按这条顺序走先看趋势用uptime或者systat的历史记录判断“慢”是突发的还是渐进的。再看资源CPU、内存、磁盘、网络哪一项逼近临界值。然后看进程是哪个进程在消耗对应资源。接着看内核系统调用、上下文切换、中断是否有异常。最后才是看代码热点函数、锁、I/O模式。每做一步建议把命令输出保存到文件。有人觉得截图就够了但截图只能看到某个瞬间而性能问题往往是间歇性的。我习惯在服务器上建个目录比如/tmp/sys_check_日期把各个命令的结果都扔进去后续复盘或者写报告时就有了完整证据链。这里还要提一个很多人忽略的点命令工具本身要提前装好。我见过太多机器上连sysstat都没装等排查时才发现iostat、sar这些都不可用。建议运维初装系统时就把sysstat、procps、iotop、perf、strace、lsof这些基础排查工具装好真到用时才不慌。至于每个工具怎么用下面我分开讲。2. 第一轮侦察uptime、top与CPU时间片2.1 读懂load average不是越大一定越糟uptime命令的输出大概是这样的$ uptime 14:23:45 up 33 days, 2:14, 3 users, load average: 8.14, 5.23, 3.01这里面最容易误导人的就是load average。很多人一看三分钟负载8.14就慌了马上觉得CPU爆了。但load average的定义是运行队列中处于可运行状态和不可中断睡眠状态的平均进程数它反映的是系统对任务的处理压力而不仅仅是CPU占用率。判断负载是否过高首先要看CPU核数。我举个例子一台8核机器load average为8说明平均每个核正好排一个进程整体处于刚刚饱和的状态系统可能已经在排队但不至于完全卡死。如果机器是16核负载8就很轻松。反过来如果一台4核机器负载到了8那相当于每个核有两个任务在等待用户体感就会明显变慢。更关键的是要理解load average高并不一定等于CPU繁忙。如果很多进程处于不可中断睡眠状态D状态比如正在等待磁盘I/O或者锁资源它们同样会计入load average。这种情况下一台机器可能负载高得吓人但CPU空闲率反而很高。所以在看到负载高时不要急着下结论要继续用top或者vmstat确认到底是CPU排队还是I/O阻塞。我自己的习惯是先用一个简单的比例判断load average除以CPU核数如果长期大于1说明系统有压力大于2到3说明已经比较严重如果只是偶发瞬间超过1那可能只是业务波动不必紧张。做判断时一定结合15分钟趋势单看一个瞬间数据很容易被突发流量误导。2.2 用top把CPU时间片拆给谁top命令是所有人都知道但大多数人只看上面几行和按CPU排序的进程列表。真正要解读系统压力你得先看顶部CPU这一行%Cpu(s): 23.5 us, 4.2 sy, 0.0 ni, 65.3 id, 5.8 wa, 0.5 hi, 0.7 si, 0.0 st这一行直接把CPU时间片分成了几类us是用户态进程消耗sy是内核态系统调用消耗id是空闲wa是等待I/O完成hi和si分别是硬中断和软中断st是虚拟机被宿主机抢占的时间。看到us高说明是应用在计算需要去进程列表里找大户看到sy高说明系统调用太频繁可能是锁竞争、上下文切换或者频繁读写看到wa高基本能断定是磁盘或存储层出了问题。这里有个细节wa高的时候即使进程列表里没有CPU大户系统也会感觉很慢。因为wa意味着CPU空转等I/O业务请求的响应时间被拉长了。另外在虚拟机环境里st这个指标非常重要如果st数值很高说明宿主机CPU资源不够分大量算力被其他虚拟机抢走这时候你再怎么优化虚拟机内部都没用得找虚拟化平台协调资源分配。进程列表的排序上我习惯在top里按大写P键让进程按CPU占用排序。但这里有个坑单核CPU被占满是100%多核机器上进程占用可能到好几千。比如一个进程占用300%CPU说明它同时跑满了三个核这种通常都是多线程程序光看进程列表还不够还得按线程看。按大写H键top就会显示线程视图这时候才能定位到具体是哪个线程在烧CPU。想更精准地观察CPU使用情况可以搭配pidstat命令。它能按进程或者线程输出CPU使用率还能指定采样间隔和次数。比如pidstat -u -p PID 1每隔一秒输出一次该进程的CPU使用率。要查线程的话用pidstat -t -p PID 1会列出进程下每个线程的CPU占用。在定位多线程应用内部热点时这两个命令比单看top高效得多。2.3 当D状态进程出现时排查时我特别留意一个特殊状态D状态也就是不可中断睡眠。这种进程正在等待某些内核资源完成操作通常是I/O。正常情况下的睡眠都是可中断的比如等待网络数据时可以响应kill命令而D状态直接挂在内核里你kill -9它都没反应。用下面命令可以快速找出系统中的D状态进程$ ps -eo state,pid,ppid,cmd | grep ^D D 12345 1 /usr/bin/java -jar app.jar如果看到大量D状态进程要么是磁盘存储出现了严重性能问题要么是文件系统层面卡住了例如NFS挂载目录失去响应、底层存储设备故障等。有个经典的排查场景服务器负载显示几百但CPU和内存都正常一查发现有大量进程在D状态睡眠最后定位到是后端存储网关异常导致所有读写请求都阻塞在那儿。这种问题靠top是不可能直接看出根因的必须沿着进程状态深挖系统调用和存储路径。处理D状态进程时千万别盲目重启相关服务。因为D状态可能是因为内核线程在等待一个尚未完成的I/O强制重启可能引起文件系统元数据不一致。正确做法是先确认底层存储是否健康检查dmesg有没有I/O错误然后视情况恢复存储或者等待系统自行超时。3. 内存与Swap慢的隐形推手3.1 free命令里的“可用内存”到底是什么很多人在看到free -h的输出时会直接拿used列判断内存用量看到used达到90%就觉得内存要爆了。其实没那么简单来看一个典型输出$ free -h total used free shared buff/cache available Mem: 30Gi 8.2Gi 1.1Gi 1.2Gi 20Gi 19Gi Swap: 8.0Gi 0B 8.0Gi这里used只有8.2G看起来不多buff/cache却占了20G。学过Linux基础的人都知道buff/cache是缓存是可回收的应用内存不足时内核会自动回收一部分来供应用使用。available字段才是真正可用的内存它已经把可回收的cache计算进去了所以在判断内存是否紧张时应该优先看available。不过有个细节容易被忽略内核回收cache也不是一瞬间就能完成的以及并不是所有cache都能立刻回收。比如被页缓存占用的内存回收时需要先写回磁盘如果磁盘I/O本身就慢回收速度就会拖后腿。极端情况下你会看到available已经很小了但内存还没被及时回收导致系统触发swap性能立刻下降。如果available经常性不足比如低于总内存的10%就应该考虑优化应用内存占用或者调整内核参数。比如vm.swappiness默认值是60如果不想频繁使用swap可以把它调低让内核更倾向于回收缓存而不是交换内存页。但这只是权宜之计归根结底要找到内存消耗大户。3.2 内存泄漏的判断与定位内存问题里最难查的就是内存泄漏。特征是进程RSS常驻内存持续增长现象上表现为系统可用内存越来越少甚至频繁触发OOMOut Of Memory杀进程。但要注意当代JVM或者Golang运行时本身会动态管理堆内存有些进程看起来占用高其实是正常现象不一定就是泄漏。正确的判断方法是看长时间趋势内存是否只增不减是否回收后仍然反弹。排查内存大户时我常用这个命令$ ps aux --sort-rss | head -10把进程按RSS排序直接看哪个进程占用物理内存最多。但定位到进程只是第一步还得深入线程甚至代码。用/proc/PID/status可以看到进程的详细内存状态例如VmRSS、VmSwap、VmPeak等其中VmSwap如果持续变大说明进程的内存页在频繁被换到swap分区这是性能踩坑的高发信号。我遇到过这样一个真实案例一个Node.js服务内存持续攀升从几百MB涨到十几GB直到被OOM Killer杀掉。开始以为是业务流量增长观察一周后发现流量没有明显变化内存却在稳步上行。后来用pmap -x PID分析进程地址空间发现某个匿名内存段占用巨大且持续增加再结合heap dump定位到业务代码里有缓存数据未清理导致内存只进不出。修复后内存稳定在2GB左右。这个案例告诉我们排查内存泄漏要有耐心盯趋势、分段定位一步跳不到代码层。如果你发现某个业务服务的内存已经对系统产生压力但暂时无法下线整改可以先用cgroup限制进程内存上限比如将服务放进一个memory限制为4G的控制组超限触发OOM或者重启至少能保护同机其他服务不受影响。这在运维应急中是个实用手段。3.3 Swap别乱清先搞懂它为什么高Swap高是性能排查里最容易让人慌乱的现象之一。系统响应慢、free显示Swap被占满第一反应可能是“把swap清掉”。但我要提醒你直接执行swapoff -a或者清swap分区是很危险的操作。因为从swap回收内存页意味着内核要把这些页重新读回物理内存这个过程本身就是I/O操作在内存极度紧张的机器上执行很可能直接把系统整卡死甚至触发OOM。正确的做法是用vmstat看swap的换入换出速率$ 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 1 2097152 51224 122056 609180 300 420 1500 1800 120 90 12 8 65 5 0重点关注siswap in和soswap out这两列。如果si和so长期大于0说明内存确实不够用系统在不断地把内存页换到磁盘、又换回内存这种抖动会严重拖垮性能。这时候的根本解法是给进程减内存需求或者加物理内存。在业务高峰期临时增加swap空间能缓解问题但治标不治本而且会掩盖真实的内存压力信号不建议长期依赖。另外补充一点内存压力大还可能表现为内核频繁进行直接回收direct reclaim这也会拖慢系统。你可以通过dmesg或/proc/vmstat里的pgscan和pgsteal指标判断内存回收的剧烈程度。如果发现这些问题优先排查进程级内存占用而不是在系统层反复调参数。4. 磁盘I/O从iowait到具体进程4.1 iostat与磁盘性能量化CPU和内存排查完了接下来要盯的就是磁盘。很多系统变慢的根源都在I/O层表现出来反而是CPU的wa升高所以两者要综合看。我排查磁盘时默认用iostat -x 1输出比普通模式详细得多$ iostat -x 1 Device r/s w/s rkB/s wkB/s avgqu-sz await r_await w_await svctm %util vda 12.0 245.0 480.0 10240.0 2.8 11.2 0.8 10.3 0.25 28.0这里面的核心字段有几个%util表示设备繁忙程度一般认为接近100%说明磁盘满负荷await是I/O请求的平均等待时间单位毫秒越高说明延迟越大avgqu-sz是I/O请求队列长度队列越长排队时间越长。理解这些指标时要注意SSD时代%util的解读逻辑跟机械盘已经不一样了。老式机械盘同一时刻只能处理一个I/O%util接近100%就是真的满了。但NVMe SSD内部有多通道并行能力即便处于高利用率状态也能同时处理大量请求。这时候想判断磁盘是否成为瓶颈应该更关注await和队列长度特别是看请求延迟是否明显上升否则容易误判。我做性能评估时习惯对比两组数据磁盘在空闲时的await基线以及业务高峰时的await值。如果高峰await超过基线的两三倍就算%util看着不高磁盘依然可能是慢的根因。另外r_await和w_await分开看很有用如果写延迟远高于读延迟多半是写缓存策略或底层存储复制机制导致的这时候应用层可以尝试合并写操作减少小文件随机写的频率。4.2 用iotop与lsof揪出真凶iostat只说系统整体磁盘忙不忙但不说清是哪个进程在忙。这时候要用iotop来看进程维度的I/O排名。运行iotop它能实时显示每个进程的读写速度和I/O占用比例打开界面跟top很像操作方式也类似。比如看到一个进程在疯狂写数据iotop会直接显示它的读写速率。这时再去分析该进程的业务行为往往很快能找到问题。$ iotop -o -P Total DISK READ: 0.00 B/s | Total DISK WRITE: 12.50 M/s TID PRIO USER DISK READ DISK WRITE SWAPIN IO COMMAND 12345 be/4 www 0.00 B/s 10.20 M/s 0.00 % 99.99 % nginx: worker process这里有个很常见但容易被忽略的坑文件已经被删除但进程依然持有文件句柄导致磁盘空间无法释放。典型场景是日志文件被应用持续写入运维为了清理磁盘直接rm了文件但进程没有重新打开日志文件空间被删除后并未真正释放df显示磁盘满了但du又找不到大文件。这时候lsof L1就能找到这种被删除但仍被进程占用的文件。处理这类问题不是杀掉进程而是让应用重新加载配置或重建日志文件句柄。比如nginx可以执行nginx -s reopenJava应用可以通过logback配置的定时rollover自动生成新文件。通过这种方式释放空间比单纯杀进程更安全也能避免因为重启导致业务中断。磁盘排查还有一个常用场景是df和du不一致。df看文件系统层级分配的空间du看每个文件实际占用当删除大量文件后df依然显示满可能就是上面说的句柄未释放也可能是文件系统元数据延迟。这时可以用lsof确认占用然后联系应用侧处理。不要一上来就umount或者强制清理风险太大。5. 网络与连接看不见的瓶颈5.1 快速检查网络现状ss vs netstat网络层面的问题往往比CPU和内存更隐蔽因为流量来无影去无踪。以前排查网络连接大家习惯用netstat但现代Linux系统上我更推荐ss它直接读取内核socket信息速度更快输出也更清晰。先用ss -s看一眼整体socket统计$ ss -s Total: 849 (kernel 912) TCP: 234 (estab 121, closed 87, orphaned 0, synrecv 0, timewait 42)如果看到timewait数量非常高比如上千说明系统里产生大量短连接连接主动关闭方处在TIME_WAIT状态等待内核回收。TIME_WAIT本身不是错误它是TCP协议为了保证最后一个ACK不会丢失而存在的一种安全状态但量级过大时会占用大量端口和内存资源。常见于高并发短连接请求尤其是使用默认配置的Java和Python服务。再配合ss -tanp查看具体的连接状态$ ss -tanp | awk {print $1} | sort | uniq -c | sort -rn 121 ESTAB 42 TIME-WAIT ...如果CLOSE_WAIT状态大量堆积情况更值得关注。CLOSE_WAIT意味着连接的对端已关闭但本地应用一直没有调用close()说明应用层面卡住了或者代码里忘了关闭连接。这种故障的特征是连接数只增不减最终占满文件描述符导致新的连接无法建立服务对外表现为“拒绝服务”。排查时先统计CLOSE_WAIT数量再看对应进程的连接来源基本就能把锅甩给具体的业务模块。另外一个容易被忽视的参数是文件句柄限制。进程能打开的socket也是文件描述符的一种当系统的nofile或fs.file-max不够时就算业务代码没问题也照样报too many open files。所以排查连接问题时顺手看下ulimit -n和相关进程的fd数量能省去很多弯路的排查时间。5.2 结合业务场景定位网络排查不能只看状态还要结合业务特征。比如数据库连接池配置过小导致连接排队等待表现为应用线程大量BLOCKED但网络本身并没有丢包前端服务流量突增连接数上涨但每连接处理速度下降可能需要看应用线程的并发模型如果机器有外网流量还可以配合iftop看实时流量来源和去向。这里要纠正一个习惯不要一觉得网络慢就去ping或者traceroute。ping通只说明网络层是通的但TCP三次握手、TLS握手、应用层响应时间是ping完全测不出来的。排查网络延迟时直接看业务请求的响应时间和TCP建连耗时更有价值。我处理过一个比较典型的案例某服务在高峰期出现大量请求超时检查CPU和内存都不高但ss -tanp发现SYN-RECV状态的连接数量异常多。SYN-RECV是TCP握手已经完成到一半的状态也就是说服务端已经收到了SYN包但三次握手没有完成。进一步检查发现这台机器的somaxconn和backlog设置偏小并且应用连接等待队列被打满新连接根本进不了accept队列。调整内核参数并优化应用线程数量后问题解决。这个案例说明网络瓶颈有时候不在网卡而在内核协议栈配置和应用层并发能力。顺带说一句排查网络问题时不要只盯着本机的出口带宽。很多“慢”其实是对端服务器的处理能力慢或者是数据库响应慢这些都表现为网络等待时间变长但根源不在网络。所以最佳实践是把网络指标和应用指标在一个时间轴上对齐观察别孤立的看某个层面。6. 深度定位热点、系统调用与内核日志6.1 perf top当进程列表骗了你前面提到的工具都属于“粗查”阶段能定位到进程级别。但有时候你找到了“嫌疑人”它CPU占用也不高系统却依然卡顿。这种“见鬼”的情况通常意味着热点在系统调用或者内核线程里普通top根本展示不出来。这时候就得拿出性能分析中的神器——perf。perf top的用法很简单$ perf top Samples: 1M of event cpu-clock, 4000 Hz Overhead Command Shared Object Symbol 25.00% swapper [kernel.kallsyms] [k] _raw_spin_unlock_irqrestore 10.00% app libc-2.17.so [.] __memset_avx2 8.00% app libjvm.so [.] JVM_DefineClass如果看到某个内核函数的overhead特别高说明系统时间都消耗在内核处理上。比如_raw_spin_unlock_irqrestore、do_sys_open这类函数频繁出现一般意味着锁竞争或者文件操作过于频繁。如果你能确认热点在某个业务进程的共享库里比如libjvm.so或者libc.so里的某个函数接着用perf annotate去细化到具体指令甚至可以看出是哪一行代码导致的性能热点。perf还有一个非常实用的场景定位“CPU占用高但进程列表正常”的神秘问题。比如前面提到load很高但us不高的情况用perf top一看发现热点全在kswapd或者kworker的内核线程上就能快速把排查方向转向内存回收和I/O子系统而不是继续纠结应用列表。这种问题用常规工具三天查不出所以然perf十分钟就能定位个大概。6.2 strace看进程卡在哪个系统调用如果perf告诉你热点在某个进程但你不知道它在干什么下一步就是用strace观察系统调用。简单用法是strace -p PID直接跟踪某个进程的所有系统调用。但生产环境要特别注意strace的跟踪开销非常大在频繁调用的进程上执行会急剧放大系统负载搞不好会加剧故障。我一般建议先用strace -p PID -c跑个几秒钟做系统调用统计而不是无脑全量跟踪$ strace -p 12345 -c -f -S time % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- -------------- 80.00 0.480000 2400 200 close 15.00 0.090000 450 200 read如果统计结果显示某个系统调用次数或者耗时异常再针对性的跟踪。比如我遇到过close()调用占80%的情况每个调用平均耗时2.4毫秒这非常反常。正常的close()应该在微秒级。后来跟踪发现进程在反复地关闭socket连接和重新建立连接相当于连接根本没有复用。顺着这条线看代码果然发现业务里每次请求都新建了一个HTTP客户端没有走连接池。优化后系统调用开销下降了一个数量级。这里还要提醒一个细节strace和perf都有一定开销在性能已经严重下降的服务器上执行时要谨慎。特别是使用-f参数跟踪子进程时会把线程和派生的子进程也纳进来输出量巨大。建议先注入较短的执行时间比如3到5秒采集统计信息后再决定是否深入。千万别长时间挂在生产环境上否则你不但解决不了原来的问题还会把自己变成新的瓶颈。6.3 dmesg与内核日志很多性能问题在应用层完全看不到蛛丝马迹但内核日志早就记录了关键证据。排查时记得执行dmesg -T把时间戳转成可读格式重点看有没有OOM相关信息、硬件I/O错误、文件系统报错、还是内核panic前的堆栈。典型的内核日志长这样$ dmesg -T [Fri Dec 20 03:12:45 2024] Out of memory: Killed process 4561 (java) total-vm:12345678kB, anon-rss:2048000kB, file-rss:0kB, shmem-rss:0kB看到这种输出就知道是OOM Killer在起作用系统在内存耗尽时自动选择“牺牲”某个进程来释放内存。很多人会抱怨OOM Killer乱杀进程老是挑重要的杀。其实内核的OOM选择算法会综合考量进程的内存占用、运行时间、优先级等因素但消息里那行Killed process后面就是你该重点关注的进程。如果它频繁被杀说明内存压力已经到极限加内存或者优化内存占用是唯一的出路。除了OOMdmesg还会暴露比如ext4文件系统报错、RAID降级、磁盘坏道、软锁up等问题。软锁soft lockup表示某个CPU核心长时间无法响应调度常见于有问题的驱动或硬件故障。这些内核级别的信号是iostat和top看不到的但它们对系统稳定性的影响往往是致命的。所以我坚持每次深度排查时都必须把dmesg日志纳入必查项。7. 常见问题速查表与避坑心得7.1 六类高频症状的定位方向我把日常运维中反复出现的几类性能场景整理成了一张速查表每次排查卡壳时我都会拿出对照一遍避免钻进死胡同。症状可能原因优先排查方向load high但CPU us/sy都不高大量D状态进程I/O阻塞ps查D状态进程iostat看awaitdmesg查硬件报错CPU us持续90%以上应用计算密集或死循环top/pstree找进程perf top找热点函数CPU sy偏高系统调用太频繁、锁竞争strace做系统调用统计检查上下文切换频率iowait高但磁盘util不高随机I/O、SSD并行瓶颈iostat -x看队列和延迟iotop找进程可用内存持续下降swap占用升高内存泄漏或容量不足ps排序RSSpmap分析进程内存段检查cgroup限制TIME_WAIT或CLOSE_WAIT堆积短连接过多未复用关闭逻辑异常ss统计连接状态配合应用代码检查连接池配置这张表不能替代完整的排查流程但可以在你迷失方向的时候快速给你一个起点。记住异常指标只是线索最终定论还是要结合日志、代码和应用场景综合判断。7.2 几条帮你少走弯路的经验做性能排查长期积累下来的经验比教科书重要得多。下面几条是我自己反复踩坑后总结出来的分享给同行参考。第一永远先把现场数据留全再动手。我自己在服务器上备了一段脚本触发性能问题时瞬间收集uptime、top、iostat、vmstat、ss、dmesg、ps等一串命令的输出全部加上时间戳存到目录里。有了现场数据后续不管是自己分析还是找专家支援都有据可查不用靠回忆猜现场。第二没有基线就没有对比。每台服务器在正常运行时的CPU、内存、磁盘I/O基线数值是不一样与其在网上搜“load多少算正常”不如平时抽时间记录业务平稳期的指标。有了基线异常数值一出现你一眼就能识别出偏离程度能精准判断问题的严重性。推荐用sar -o参数周期性落盘保留个把月的运行数据排查历史性能问题时受益无穷。第三虚拟机环境里多看一眼steal。很多人排查云服务器性能问题时盯着用户态CPU看了半天却忽略了ststeal time指标。steal是物理机抢占虚拟CPU的时间如果它持续偏高说明你的云主机邻居正在大量消耗宿主机资源这时候优化虚拟机内的配置意义有限优先考虑调整虚拟机规格或者迁移实例。第四工具别贪多把常用的玩透。有人一学性能排查就装了二三十个工具结果每个都只会跑默认参数输出看不太懂反而越查越乱。我建议先把uptime、top、vmstat、iostat、ss、perf这个组合练熟形成自己的固定排查流程再根据实际场景扩展。深度比广度重要得多。第五事后一定要复盘记录。性能问题排查完不是结束写一份简短的事故报告记录现象、排查链路、根因和解决方案花不了半小时但下一次遇到类似问题时这份wiki就是最高效的排查指南。我这些年处理过的故障有相当一部分是同类问题反复出现的前期记录越扎实后期处理越轻松。我个人在实际操作中的体会是Linux性能排查更大的挑战不是某一个工具用不熟而是在信息和噪音之间快速筛出真正有价值的线索。“系统慢”只是表象背后的根因可能藏在一堆看似正常的指标夹缝里。从uptime到perf、从进程列表到内核日志这套方法真正跑通了之后你会发现自己看系统的眼光完全不一样了。最后再分享一个小技巧排查时把watch -n 1 uptime; free -h; iostat -x 1 1串起来实时刷新核心指标很多隐藏的规律会在你盯着数据变化时突然浮现出来。