Skip to content

Menu
Menu

Linux 性能问题排查思路

Posted on 2022年4月9日2026年1月11日 by zhezimi

当登录到一台表现不佳的Linux系统中后,我们可以进行以下步骤来排查问题。

  1. 查看平均负载
  2. 查看系统日志
  3. 查看cpu饱和度
  4. 查看磁盘饱和度
  5. 查看内存饱和度
  6. 查看网络饱和度
  7. 跟踪进程

步骤1:查看平均负载

[root@VM-12-4-centos ~]# uptime 
16:49:58 up 7 days, 19:49, 4 users, load average: 0.94, 0.66, 0.50

最后三个数字分别表示 1 / 5 / 15 分钟内的平均负载。通过对比它们的变化趋势,可以判断系统负载是在上升、下降还是保持稳定。

平均负载(Load Average)表示系统对 CPU 的总体需求,它同时包含:

  • 正在 CPU 上运行的线程
  • 正在等待 CPU 或处于不可中断状态(如 I/O)的线程

当 平均负载大于 CPU 数量 时,说明 CPU 资源已经不足,部分线程需要排队等待;
当 平均负载小于 CPU 数量 时,通常表示系统仍有余量,线程大多可以及时获得 CPU 执行。

举例来说,一个拥有 64 个 CPU 的系统:

  • 平均负载为 128:表示平均每个 CPU 上 1 个线程在运行、1 个线程在等待
  • 平均负载为 10:说明系统负载很低,还有大量 CPU 资源尚未被使用

因此,在评估平均负载时,必须先明确系统的 CPU 数量,可以通过 top 或 /proc/cpuinfo 获取,例如:

[root@VM-12-4-centos ~]# grep 'model name' /proc/cpuinfo | wc -l

当平均负载高于 CPU 数量 70% 的时候,你就应该分析排查负载高的问题了。一旦负载过高,就可能导致进程响应变慢,进而影响服务的正常功能。

但 70% 这个数字并不是绝对的,最推荐的方法,还是把系统的平均负载监控起来,然后根据更多的历史数据,判断负载的变化趋势。当发现负载有明显升高趋势时,比如说负载翻倍了,你再去做分析和调查。

系统的平均负载值还是一个优秀指标,可以作为系统基准数据的一部分进行跟踪。如果知道您的系统在普通工作日的系统平均负载,而在有问题的同一天也处于同样的范围,这就是暗示您应该看看别的方面(如网络)来确定性能问题的原因。如果平均负载超出预期的正常水平,则表明您应该看看系统自身所运行的进程。

在linux上最好通过一些其他的指标料及CPU负载,例如vmstat和mpstat提供的一些数据。

步骤2:查看系统日志

[root@VM-12-4-centos ~]# dmesg |tail
[ 576.408049] atkbd serio0: Unknown key pressed (translated set 2, code 0x0 on isa0060/serio0).
[ 576.408749] atkbd serio0: Use 'setkeycodes 00 ' to make it known.
[ 576.738079] atkbd serio0: Unknown key released (translated set 2, code 0x0 on isa0060/serio0).
[ 576.738874] atkbd serio0: Use 'setkeycodes 00 ' to make it known.
[452528.220798] hrtimer: interrupt took 4380755 ns
[2505242.669943] conntrack: generic helper won't handle protocol 47. Please consider loading the specific helper module.
[3040185.594969] python3[26454]: segfault at a9 ip 0000000000549478 sp 00007ffcabffe870 error 4 in python3.7[400000+29e000]
[8552308.399053] TCP: request_sock_TCP: Possible SYN flooding on port 22. Sending cookies. Check SNMP counters.
[21887551.894806] AliSecGuard : 1818d2bba043a57cfe9bbe06fb701e2825c6e66d
[21887552.136283] AliSecGuard : 1818d2bba043a57cfe9bbe06fb701e2825c6e66d

这个命令显示过去10条系统日志,如果有的话,注意在这里寻找可能导致性能问题的错误。

我们还可以查看下/var/log/message 的内容。

步骤3:查看CPU饱和度

[root@VM-12-4-centos ~]# mpstat -P ALL 1
Linux 3.10.0-1160.114.2.el7.x86_64 (izuf67tjsjwg8yv8bjejo1z)    01/11/2026      _x86_64_        (4 CPU)

10:18:19 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
10:18:20 PM  all    0.50    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00   99.50
10:18:20 PM    0    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00
10:18:20 PM    1    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00
10:18:20 PM    2    1.01    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00   98.99
10:18:20 PM    3    1.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00   99.00

10:18:20 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
10:18:21 PM  all   12.06    0.00    2.51    0.00    0.00    0.00    0.00    0.00    0.00   85.43
10:18:21 PM    0    1.02    0.00    1.02    0.00    0.00    0.00    0.00    0.00    0.00   97.96
10:18:21 PM    1   13.00    0.00    2.00    0.00    0.00    0.00    0.00    0.00    0.00   85.00
10:18:21 PM    2   17.17    0.00    3.03    0.00    0.00    0.00    0.00    0.00    0.00   79.80
10:18:21 PM    3   16.00    0.00    4.00    0.00    0.00    0.00    0.00    0.00    0.00   80.00

这个命令将每个CPU分解到各个状态下的时间打印出来。选项-P ALL 用来打印每个CPU的报告,mpstat默认只打印系统级别的总结信息。

输出列如下:

  • CPU:逻辑CPU ID或者all表示总结信息
  • %usr:用户态时间
  • %nice:以nice优先级运行的进程用户态时间
  • %sys:系统态时间(内核)
  • %iowait:I/O等待
  • %irq:硬件中断CPU用量
  • %sort:软件中断CPU用量
  • %steal:耗费在服务其他租户的时间
  • %guest:花在访客虚拟机的时间
  • %idle:空闲

重要的有%usr,%sys,%idle。这些显示了每个CPU的用量以及用户态和内核态的时间比例。

这同样也能表明”热“CPU—那些跑到100%使用率(%usr+%sys)的CPU,而其他CPU并未跑满—–可能是由单线程应用程序的负载或者设备中断映射造成。

CPU花在执行用户态应用程序代码的时间称为用户态时间,而执行内核态代码的时间称为内核态时间。内核态时间包括了系统调用,内核线程和中断的时间。当在整个系统范围内进行测量时,用户态时间和内核态时间之比揭示了运行的负载类型。

计算密集的应用程序几乎会把大量的时间用在用户态代码上,用户态/内核态时间之比接近99/1。这类例子有图像处理,基因组学和数据分析。

I/O密集型的应用程序的系统调用频率较高,通过执行内核代码执行I/O操作。例如,一个进行网络I/O的Web服务器的用户态/内核态时间比大约为70/30。

这些数字依赖许多因素,只是用来表示预期的比例。

对于比较高的%iowait时间也要注意,可以使用磁盘I/O工具进一步分析。如果出现较高的%sys值,可以使用系统调用(syscall)跟踪和内核跟踪,以及CPU剖析手段进一步分析。我们可以用以下命令来查出是哪些进程占用了更多的CPU。

[root@VM-12-4-centos ~] pidstat 1 

直接运行 pidstat 默认显示所有进程的 CPU 使用信息,等效于 `pidstat -u -p ALL。

Linux 3.10.0-1160.114.2.el7.x86_64 (izuf67tjsjwg8yv8bjejo1z)    01/11/2026      _x86_64_        (4 CPU)

10:19:21 PM   UID       PID    %usr %system  %guest    %CPU   CPU  Command
10:19:22 PM     0       584    0.98    0.00    0.00    0.98     3  exe
10:19:22 PM     0      2730    1.96    0.00    0.00    1.96     1  AliYunDunMonito
10:19:22 PM  1009     24863    0.00    0.98    0.00    0.98     0  pidstat

10:19:22 PM   UID       PID    %usr %system  %guest    %CPU   CPU  Command
10:19:23 PM     0      2350    0.00    1.00    0.00    1.00     0  AliYunDun
10:19:23 PM     0      2730    2.00    1.00    0.00    3.00     1  AliYunDunMonito
10:19:23 PM  1009     24863    1.00    2.00    0.00    3.00     0  pidstat

10:19:23 PM   UID       PID    %usr %system  %guest    %CPU   CPU  Command
10:19:24 PM     0       584    0.00    1.00    0.00    1.00     3  exe
10:19:24 PM     0      2730    3.00    0.00    0.00    3.00     2  AliYunDunMonito
10:19:24 PM     0      3300    1.00    0.00    0.00    1.00     2  ilogtail
10:19:24 PM  1000     20259    1.00    0.00    0.00    1.00     3  java
10:19:24 PM  1009     24863    0.00    1.00    0.00    1.00     0  pidstat

10:19:24 PM   UID       PID    %usr %system  %guest    %CPU   CPU  Command
10:19:25 PM     0       366   13.00   22.00    0.00   35.00     2  BT-Task
10:19:25 PM     0      2730    2.00    0.00    0.00    2.00     2  AliYunDunMonito
10:19:25 PM  1009     24863    0.00    1.00    0.00    1.00     0  pidstat

输出列如下:

  • PID:进程ID
  • %usr:进程在用户级(应用程序)执行时所使用的CPU百分比
  • %system:进程在系统级执行时所使用的CPU百分比(内核)。
  • %guest:进程在虚拟机(运行虚拟处理器)中消耗的CPU百分比。
  • %CPU:进程使用的CPU时间的总百分比
  • CPU:进程所在的CPU编号。
  • Command:进程名

pidstat(1)命令按每个进程展示CPU的使用情况。top(1)命令虽然也很流行,但是pidstat(1) 默认支持滚动打印输出,这样可以采集到不同时间段的数据变化。

步骤4:查看磁盘饱和度

[root@VM-12-4-centos ~]  iostat -xz 1
Linux 3.10.0-1160.114.2.el7.x86_64 (izuf67tjsjwg8yv8bjejo1z)    01/11/2026      _x86_64_        (4 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           4.09    0.00    1.82    0.44    0.00   93.66

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
vda              11.73    10.60   42.91   16.64  1182.58   151.87    44.81     0.05    0.88    3.42    4.43   0.33   1.98

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           3.27    0.00    0.76    0.25    0.00   95.72

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
vda               0.00    13.00    0.00   12.00     0.00   100.00    16.67     0.01    0.67    0.00    0.67   0.92   1.10

这个工具显示了存储设备的I/O指标。

要检查的列包括如下几个:

  • r/s,w/s,rkB/s,wkB/s:这些是每秒向设备发送的读,写次数以及读,写字节数。可以用这些指标对业务负载画像。某些性能问题仅仅是因为超过了能够承受的最大负载导致的。
  • await:I/O的平均响应时间,以毫秒为单位。这是应用需要承受的时间,它同时包含了I/O队列时间和服务时间。超过预期的平均响应时间,可看作设备已饱和或者设备层面有问题的表征。
  • avgqu-sz: 设备请求队列的平均长度,比1大的值有可能是发生饱和的表征(不过对有些设备,尤其是对基于多块磁盘的虚拟设备来说,通常以并行方式处理请求)。
  • %util:设备使用率,这是设备繁忙程度的百分比,显示了每秒设备开展实际工作的时间占比,不过它展示的并不是容量规划意义下的使用率,因为设备可以并行处理请求。大于60%的值通常会导致性能变差(可以通过await字段确认),不过这也取决于具体设备,接近100%的值通常代表了设备达到饱和状态。

我们可以使用下面的命令来查出哪些进程占用了更多的磁盘。

[root@VM-12-4-centos ~]pidstat -d 
Linux 3.10.0-1160.114.2.el7.x86_64 (izuf67tjsjwg8yv8bjejo1z)    01/11/2026      _x86_64_        (4 CPU)

10:23:23 PM   UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s  Command
10:23:23 PM  1009     25780      0.00      0.00      0.00  bash

输出列如下:

  • UID:用户ID
  • PID:进程ID
  • kB_rd/s: 每秒进程从磁盘读取的数据量 KB 单位
  • kB_wr/s: 每秒进程向磁盘写的数据量 KB 单位
  • kB_ccwr/s: 每秒进程向磁盘写入,但是被取消的数据量
  • iodelay: 块I/O延迟
  • Command: 进程名

步骤5:查看内存饱和度

[root@VM-12-4-centos ~]free -m
              total        used        free      shared  buff/cache   available
Mem:           7551        5502         168          93        1881        1658
Swap:          1024         312         712

这个输出显示了用MB作为单位的可用内存。检查可用内存(available)是否接近0,这个值显示了在系统中还有多少实际剩余内存可用,包括缓冲区和页缓存区。将一些内存用于缓存可以提升文件系统的性能。

[root@VM-12-4-centos ~] vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  0 320000 161364 191116 1742704    0    0   298    38    0    0  4  2 94  0  0
 1  0 320000 163024 191124 1742744    0    0     0   432 3809 6990  2  2 96  1  0
 0  0 320000 163148 191124 1742744    0    0     0     0 3683 6829  3  1 96  0  0
 0  0 320000 163148 191132 1742748    0    0     4   104 3476 6764  1  0 99  0  0
 0  0 320000 161612 191132 1742748    0    0     0     0 3736 7173  1  1 99  0  0
 0  0 320000 161488 191132 1742752    0    0     0   128 3601 6853  0  0 99  0  0
 0  0 320000 161340 191132 1742752    0    0     0     0 3432 6666  0  0 99  0  0
 0  0 320000 161240 191132 1742756    0    0     0     0 3337 6532  0  0 100  0  0
 0  0 320000 161240 191132 1742756    0    0     0   164 3440 6702  1  0 99  0  0
 0  0 320000 161240 191132 1742756    0    0     0     0 3544 6853  1  0 99  0  0

输出如下,单位为KB:

  • swap: 交换出的内存量
  • free:空闲的可用内存
  • buff:用于缓冲缓存的内存
  • cache:用于页缓存的内存
  • si:换入的内存(换页)
  • so:换出的内存

如果si和so列一直非0,那么系统正存在内存压力并换页到交换设备或文件。我们可以使用pidstat工具来查出是哪些进程占用了更多的内存。

[root@VM-12-4-centos ~] pidstat -r 2 10 
Linux 3.10.0-1160.114.2.el7.x86_64 (izuf67tjsjwg8yv8bjejo1z)    01/11/2026      _x86_64_        (4 CPU)

10:25:39 PM   UID       PID  minflt/s  majflt/s     VSZ    RSS   %MEM  Command
10:25:41 PM     0       584      2.97      0.00 1506924  24724   0.32  exe
10:25:41 PM     0      2730      8.91      0.00  264768 114204   1.48  AliYunDunMonito
10:25:41 PM     0      3300      1.49      0.00  338636  23164   0.30  ilogtail
10:25:41 PM     0     22792      0.50      0.00  690116   8128   0.11  aliyun-service
10:25:41 PM  1009     25545    349.01      0.00  108668   1340   0.02  pidstat

10:25:41 PM   UID       PID  minflt/s  majflt/s     VSZ    RSS   %MEM  Command
10:25:43 PM     0       530      1.00      0.00  743836  15720   0.20  hbrclient
10:25:43 PM     0       536      7.50      0.00   21672    452   0.01  irqbalance
10:25:43 PM     0       584      3.00      0.00 1506924  24724   0.32  exe
10:25:43 PM     0      2730      2.00      0.00  264768 114204   1.48  AliYunDunMonito
10:25:43 PM  1009     25545    315.50      0.00  108668   1432   0.02  pidstat

输出列如下:

  • UID:用户ID
  • PID:进程ID
  • Minflt/s : 每秒次缺页错误次数 (minor page faults),虚拟内存地址映射成物理内存地址产生的 page fault 次数
  • Majflt/s : 每秒主缺页错误次数 (major page faults), 虚拟内存地址映射成物理内存地址时,相应 page 在 swap 中
  • VSZ virtual memory usage : 该进程使用的虚拟内存 KB 单位
  • RSS : 该进程使用的物理内存 KB 单位
  • %MEM : 内存使用率
  • Command : 该进程的命令 task name

步骤6:查看网络饱和度

系统活动报告工具sar(1)可以观测当前活动并且能配置为保存和报告历史统计数据。

Linux版本用以下选项提供网络统计信息。

  • -n DEV:网络接口统计信息。
  • -n EDEV:网络接口错误。
  • -n IP:IP 数据报统计信息。
  • -n EIP:IP 错误统计信息。
  • -n TCP:TCP 统计信息。
  • -n ETCP:TCP 错误统计信息。
  • -n SOCK:套接字使用。
 [root@VM-12-4-centos ~] sar -n DEV 1
Linux 3.10.0-1160.114.2.el7.x86_64 (izuf67tjsjwg8yv8bjejo1z)    01/11/2026      _x86_64_        (4 CPU)

10:26:39 PM     IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s
10:26:40 PM      eth0      6.00      3.00      0.37      2.65      0.00      0.00      0.00
10:26:40 PM        lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00

10:26:40 PM     IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s
10:26:41 PM      eth0     19.00     24.00      3.09      5.15      0.00      0.00      0.00
10:26:41 PM        lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00

10:26:41 PM     IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s
10:26:42 PM      eth0      4.00      5.00      0.50      2.48      0.00      0.00      0.00
10:26:42 PM        lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00

10:26:42 PM     IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s
10:26:43 PM      eth0      1.00      1.00      0.06      0.06      0.00      0.00      0.00
10:26:43 PM        lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00

将不同的指标进行组合,sar(1)工具具有不同的运行模式。在这个例子中,我们使用它来看网络设备指标。通过接口吞吐量信息rxkB/s和txkB/s来检查是否有指标达到了上限。

[root@VM-12-4-centos ~] sar -n TCP,ETCP 1
Linux 3.10.0-1160.114.2.el7.x86_64 (izuf67tjsjwg8yv8bjejo1z)    01/11/2026      _x86_64_        (4 CPU)

10:27:11 PM  active/s passive/s    iseg/s    oseg/s
10:27:12 PM      0.00      0.00      7.00      6.00

10:27:11 PM  atmptf/s  estres/s retrans/s isegerr/s   orsts/s
10:27:12 PM      0.00      0.00      1.00      0.00      0.00

10:27:12 PM  active/s passive/s    iseg/s    oseg/s
10:27:13 PM      0.00      0.00      7.00      7.00

10:27:12 PM  atmptf/s  estres/s retrans/s isegerr/s   orsts/s
10:27:13 PM      1.00      0.00      1.00      0.00      0.00

10:27:13 PM  active/s passive/s    iseg/s    oseg/s
10:27:14 PM      0.00      0.00      7.00      5.00

现在我们使用sar(1)工具来查看TCP指标和TCP错误信息,相关的字段包括如下几个:

  • active/s:每秒本地发起的TCP连接的数量(通过调用connect()创建)
  • passive/s:每秒远端发起的TCP连接的数量(通过调用accept()创建)
  • retrans/s:每秒TCP重传的数量

主动和被动连接计数对业务负载画像很有用。重传则是网络或者远端主机有问题的征兆。

[root@VM-12-4-centos ~] netstat

基于使用的选项,netstat(8)命令能报告多种类型的网络统计数据,就像具有多种功能的组合工具。

选项介绍如下:

  • (默认):列出连接的套接字。
  • -a:列出所有套接字的信息。
  • -s:网络栈统计信息。
  • -i:网络接口信息。
  • -r:列出路由表。
[root@VM-12-4-centos ~]# netstat -i
Kernel Interface table
Iface             MTU    RX-OK RX-ERR RX-DRP RX-OVR    TX-OK TX-ERR TX-DRP TX-OVR Flg
eth0             1500 874929364      0      0 0      1060892268      0      0      0 BMRU
lo              65536 145930374      0      0 0      145930374      0      0      0 LRU

数据列包括网络接口(Iface)、MTU,以及一系列接收(RX-)和传输(TX-)的指标。

  • OK:成功传输的数据包。
  • ERR:错误数据包。
  • DRP:丢包。
  • OVR:超限。

丢包和超限是网络接口饱和的指针。-c 连续模式能与-i 一并使用,每秒输出这些累积的计数器。它提供计算数据包速率的数据。

步骤7:跟踪进程

strace

strace常用来跟踪进程执行时的系统调用和所接收的信号。

在Linux世界,进程不能直接访问硬件设备,当进程需要访问硬件设备(比如读取磁盘文件,接收网络数据等等)时,必须由用户态模式切换至内核态模式,通过系统调用访问硬件设备。

strace可以跟踪到一个进程产生的系统调用,包括参数,返回值,执行消耗的时间。

-f表示跟踪子进程和子线程,-T表示显示系统调用的时长,-tt表示显示跟踪时间。

$ strace -f -T -tt -p pid
perf

perf利用Linux的trace特性,可以用于实时跟踪,统计event计数(perf stat);或者使用采样(perf record),报告(perf report|script|annotate)的使用方式进行诊断。

$ perf top -g -p pid

按方向键切换到 php-fpm,再按下回车键展开 php-fpm 的调用关系,你会发现,调用关系最终到了BF_crypt。接下来看下哪个地方调用了这个库,把对应的代码改下就可以了。

参考资料:

《性能之巅 洞悉系统,企业与云计算》

《BPF性能之巅》

《UNIX/Linux 系统管理技术手册》

https://man7.org/linux/man-pages/man1/perf-top.1.html

相关文章

  • 排查网络故障常用命令

  • 网络I/O模型

  • grep

  • 《shell脚本攻略》笔记

  • vim常规使用

发表评论 取消回复

您的电子邮箱地址不会被公开。 必填项已用*标注

近期文章

  • 排查网络故障常用命令
  • PHP-FPM异常问题
  • RabbitMQ 1:介绍
  • 观察者模式
  • 装饰者模式

近期评论

没有评论可显示。

分类

  • cdn
  • css
  • docker
  • git
  • http
  • javascript
  • linux
  • mysql
  • nginx
  • php
  • RabbitMQ
  • 代码规范
  • 性能
  • 正则表达式
  • 网络协议
  • 设计模式
© 2026 | Powered by Minimalist Blog WordPress Theme