我们不能失去信仰

我们在这个世界上不停地奔跑...

0%

平均负载的理解

使用 uptime 命令可以简洁的了解系统的负载情况:

1
2
3
$ uptime
09:46:05 up 7:13, 1 user, load average: 0.62, 0.39, 0.37
当前时间 系统运行时间 正在登陆的用户数 1 分钟 5 分钟 15 分钟的平均负载

可以通过查到最后三个数字来判断服务器的负载情况,如果是从左到右依次减小,那么说明系统目前的负载是在升高的,如果从左到右依次增加,那么说明系统目前的负载是在下降的。

平均负载代表的是单位时间内,系统处于可运行状态(ps命令中处于 R 状态 Running/Runnable)和不可中断状态(ps 命令中处于 D 状态 Uninterruptible Sleep, 也称为 Disk Sleep)的平均进程数,也就是平均活跃进程数,它和 CPU使用率 没有直接关系。

平均负载最理想的情况是等于 CPU 个数, 可以通过 cat /proc/cpuinfo 来进行查看 CPU 的信息。当平均负载高于 CPU 数量 70% 的时候,可能就已经开始影响进程服务,导致其变慢。

平均负载跟CPU使用率没有直接关系

CPU 使用率,是单位时间内 CPU 繁忙情况的统计,跟平均负载并不一定完全对应。比如:

  • CPU 密集型进程,使用大量 CPU 会导致平均负载升高,但 CPU 使用率不一定高
  • I/O 密集型进程, 等待 I/O 也会导致平均负载升高,但 CPU 使用率不一定很高
  • 大量等待 CPU 的进程调度也会导致平均负载升高,此时的 CPU 使用率也会比较高

实践

可使用 stress 软件进行负载模拟, 使用 sysstat 进行分析

stress 是一个 Linux 系统压力测试工具,这里我们用作异常进程模拟平均负载升高的场景。

而 sysstat 包含了常用的 Linux 性能工具,用来监控和分析系统的性能。我们的案例会用到这个包的两个命令 mpstat 和 pidstat。

  • mpstat 是一个常用的多核 CPU 性能分析工具,用来实时查看每个 CPU 的性能指标,以及所有 CPU 的平均指标。
  • pidstat 是一个常用的进程性能分析工具,用来实时查看进程的 CPU、内存、I/O 以及上下文切换等性能指标。

在 Linux 上面,切换到 Root 用户进行操作,否则可能看到的东西会因为权限问题而被阉割掉。

CPU 密集进程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
终端1:
stress --cpu 1 --timeout 600

终端2:
# -d 参数表示高亮显示变化的区域
$ watch -d uptime
..., load average: 1.00, 0.75, 0.39

终端3:
# -P ALL 表示监控所有 CPU,后面数字 5 表示间隔 5 秒后输出一组数据
$ mpstat -P ALL 5
Linux 4.15.0 (ubuntu) 09/22/18 _x86_64_ (2 CPU)
13:30:06 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
13:30:11 all 50.05 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 49.95
13:30:11 0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00
13:30:11 1 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00

可以看出来,平均负载慢慢的向 1靠近。iowait 一直是0。这说明导致平均负载升高的是因为 CPU的使用率为 100% 。

接下来可以通过 pidstat 来查询具体是哪个进程导致的:

1
2
3
4
5
# 间隔 5 秒后输出一组数据 -u 表示 cpu 指标
pidstat -u 5 1

13:37:07 UID PID %usr %system %guest %wait %CPU CPU Command
13:37:12 0 2962 100.00 0.00 0.00 0.00 100.00 1 stress

可以看到正式我们的 stress 进程。

I/O 密集型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 终端1 执行:
$ stress -i 1 --timeout 600
# 模拟 I/O 压力,即不停地执行 sync

# 终端2 执行:
$ watch -d uptime
..., load average: 1.06, 0.58, 0.37

# 终端3 查看 CPU 使用率变化:
# 显示所有 CPU 的指标,并在间隔 5 秒输出一组数据
$ mpstat -P ALL 5 1
Linux 4.15.0 (ubuntu) 09/22/18 _x86_64_ (2 CPU)
13:41:28 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
13:41:33 all 0.21 0.00 12.07 32.67 0.00 0.21 0.00 0.00 0.00 54.84
13:41:33 0 0.43 0.00 23.87 67.53 0.00 0.43 0.00 0.00 0.00 7.74
13:41:33 1 0.00 0.00 0.81 0.20 0.00 0.00 0.00 0.00 0.00 98.99

可以看出平均负载慢慢增加到 1.06, 其中一个 CPU 的使用率升高到 23.87, 而 iowait 高达 67.53% 。 这说明,平均负载的升高是由于 iowait 的升高。

依旧使用 pidstat 进行查询具体是哪个进程,执行:

pidstat -u 5 1

大量进程场景

2核cpu ,开8个进程进行测试:

1
2
3
4
5
6
7
8
9
10
11
# 第一个终端:
stress -c 8 --timeout 600

# 第二个终端:
watch -d uptime
可以观察负载一直在升高

# 第三个终端:

pidstat -u 5 1
你可能会发现 %wait 普遍高很多。 可以看出 8个进程争抢 2个 CPU,每个进程等待 CPU 的时间即%wait 列很长,这些超出 CPU 计算能力的进程,最终导致 CPU 过载。

总结

平均负载提供了一个快速查看系统整体性能的手段,反映了整体的负载情况。但只看平均负载本身,我们并不能直接发现到底哪里出了瓶颈。所以在看平均负载时也要注意:

  • 平均负载高可能是 CPU 密集型进程导致的
  • 平均负载高并不代表 CPU 使用率高,还有可能是 I/O 更繁忙了
  • 当发现平均负载高的时候,可以使用 mpstat、pidstat 等工具,辅助分析负载的来源。