几年前在深信服工作时整理出来的一篇文章,突然需要找了好久才找到,归档记录一下。

一、负载高的原因

通常,我们说的负载高是指CPU高,因为负载的直接体现是CPU。CPU在某个时刻要处理的任务多了,处理不过来,就会出现负载高的情况。

导致负载高的问题主要有以下几个:

  • CPU自身性能不够,系统和任务多,无法处理这么多任务。
  • 内存不足,会频繁触cache回收,有时会杀掉很多进程,导致CPU高。
  • IO高,进程持续高IO读写,导致CPU大部分时间都用来处理系统IO了。

排查负载的的主要思路:uptime ==> mpstat ==> free ==> dmesg ==> tcpdump。

二、分析CPU占用

2.1 分析uptime

uptime命令可以看到系统的运行时间,和当前系统负载:

12:46:32 up 148 days, 19:18, 2 users, load average: 0.00, 0.01, 0.05 

后面的load average表示系统的负载,三个数值分别表示1分钟、5分钟以及15分钟的平均负载。“负载”可以简单理解成当前CPU需要执行的任务数量,如果同一时刻CPU只用处理1个或者1个不到的任务,那么基本上是没有问题的,可以认为CPU不是那么繁忙。如果同一时刻负载需要处理2个、3个甚至更高,CPU可能就比较繁忙了。

一般来说,当单核CPU负载超过3时,就可以认为负载较高了。注意这里说的是单核CPU,如果是多核,对应的负载也要乘以核数。如当前系统核数等于4,那么负载超出12就是比较高的。当然,这个3也不是严格固定的,只是一个大概的范围,负载高低可以根据这个因子大概推断。例如4核的设备,负载在10左右也属于偏高了。

这个3是根据历史数据分析大概得到的,并非完全的界定值。具体是否高还需要分析mpstat数据,两者结合来看。在多核CPU场景(特别是CPU数量较多的时候,如56核、96核的设备),可能某些CPU已经跑满了,但是实际的负载就被平均下来了。

查看CPU核数的办法:

cat /proc/cpuinfo | grep name | wc -l

设备的负载状态可以使用uptime分析工具来辅助分析,把黑匣子中整天的uptime数据直接复制进去就可以画出负载图形:

image.png

根据趋势图很容易就能看到负载高的时间点,然后根据时间点去看mpstat记录,定位具体导致负载高的原因。

2.2 mpstat分析

mpstat是对CPU的抽样,基本的用法:

mpstat -P ALL 1 3

参数-P ALL表示打印出所有CPU的采样数据,ALL也可以改成对应的CPU号表示显示指定CPU抽样数据。如果不加这个参数,命令只会打出所有CPU的平均值,不会打印出详细的每个CPU数据。后面的1 3表示每1秒打印1次,一共打印3次,3也可以省略,命令会一直持续打。输出的内容:

Linux 3.10.0-957.21.3.el7.x86_64 (vm2019)     04/14/2020     _x86_64_    (2 CPU)

11:33:26 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
11:33:27 PM  all    0.00    0.00    0.51    0.00    0.00    0.00    0.00    0.00    0.00   99.49
11:33:27 PM    0    0.00    0.00    1.00    0.00    0.00    0.00    0.00    0.00    0.00   99.00
11:33:27 PM    1    0.00    0.00    1.00    0.00    0.00    0.00    0.00    0.00    0.00   99.00

每一列的数之表示当前模块占用的CPU百分比,最后一列idle表示空闲比例。其他常见列的含义:

  • usr: CPU花费在用户态调用的时间
  • nice: CPU花费在程序调度上时间
  • sys: CPU花费在系统调用上的时间
  • iowait: CPU花费在IO上的时间
  • irq: CPU花费在硬件中断上的时间
  • soft: CPU花费在软件中断上的时间

usr/sys/nice高

usr和sys和nice高比较少见,它们高基本上是应用层程序占用导致,如果是他们高,下一步思路是定位到具体的应用程序。常见的办法是通过top命令跟踪看到底是哪个程序占用的CPU:

执行top命令后,会展示出当前系统环境下进程的资源消耗,默认每秒会统计一次并刷新。同时,这个界面是一个交互式的界面,还可以继续输入参数进去,可以用来对进程排序等A座。例如判断CPU占用的场景,可以输入P来对进程CPU使用排序。因此很容易能找到占用CPU高的程序,然后根据进程功能和工作场景判断,或者使用第三方profile工具来对程序抽样。

iowait高

iowait高有两种常见的场景:

  1. 进程在进行大量IO操作
  2. 内存不足,释放系统在回收cache资源

低端平台下的大部分场景,都是内存不足导致的,内存不足触发cache回收,把缓存的IO数据瞬间刷到磁盘,导致iowait高。

这一点在下面的内存分析中会再详细说明。

soft高

soft高表示设备软中断多,这种情况下,多半是网络环境中存在异常流量,要针对LAN或者WAN抓包分析数据。

抓包主要分析的要素:

  1. SYN/FIN等包的比例是否正常,如果比例超过总抓包数量的10,就很异常了。
  2. 数据包内容是否有问题,这里经常出现问题的就是代理环境,经常有客户端的包都是错误的。
  3. 流量流速是否正常,是否有突发流量。

异常流量可以参考上面的案例来抓包排查,异常流量一般都是很难定位的,需要大量的抓包和分析才行。

三、分析内存

查看系统当前内存状态的命令是free,输出内容为:

[maqianos@vm2019:~]$ free -m
              total        used        free      shared  buff/cache   available
Mem:           3789        1408         367           0        2013        2070
Swap:             0           0           0

这里需要重点关注的是free和cache两列,free表示的是剩余内存,cache表示的是缓存下来的IO数据。linux为了提升系统性能,会把一部分IO数据缓存在内存里面,内存不足或者触发了回收的阈值时,会自动清理cache,把数据写到磁盘。很多时候,cache会突然下降了几百兆,造成IO高,CPU瞬间跑满。

这些cache也是可以执行命令手动释放的:

echo 3 > /proc/sys/vm/drop_caches

除了free以外,top命令也可以统计进程占用的内存大小,执行完top后输入M可以对进程占用的内存排序。这样很容易定位到内存的使用者,如果能发现内存在持续增长,说明可能存在内存泄漏,需要调试进程的内存泄露。

四、流量分析

流量是负载分析中最重要的一环,很多场景负载高都是因为流量导致的。分析流量就是要抓包,流量异常的场景,抓包很容易就能看出来。对流量而言,一个非常重要的信息就是dmesg,流量异常dmesg中会打印很多很明显的日志信息。

例如:

  • Out of socket memory
  • TCP: too many of orphaned sockets
  • TCP: time wait bucket table overflow
  • possible SYN flooding on port 9090. Sending cookies.

这些都是典型的异常日志,属于非业务层面的日志,一旦出现这种问题,就需要重视了。

这种场景就要抓包了,抓包主要需要观察的几个点:

  • 各种数据包比例是否正常,比如SYN/FIN这些特殊包的发包频次,是否特别高。

单用户统计,是否存在单个IP发包特别多的情况。

  • 代理场景下关注代理的数据包是否有问题,腾讯系的产品经常会出现这种问题。

五、参考

最后修改:2022 年 03 月 18 日
喜欢就给我点赞吧