系统swap变高了(下)

网友投稿 267 2022-11-04


系统swap变高了(下)

问题:当 Swap 使用升高时,要如何定位和分析呢?

一、案例

1.1、环境准备

案例基于 Ubuntu 18.04,同样适用于其他的 Linux 系统。

机器配置:2 CPU,8GB 内存预先安装 sysstat 等工具,如​​apt install sysstat​​案例所有命令默认root用户运行

1.2、终端运行free,查看swap的使用情况

$ free total used free shared buff/cache availableMem: 8169348 331668 6715972 696 1121708 7522896Swap: 0 0 0

输出中可以看到,Swap的大小是0,说明机器没有配置Swap

为了案例继续,需要先配置、开启Swap。

Linux支持两种类型的Swap,即Swap分区和Swap文件。以Swap文件为例,配置Swap文件的大小为8GB。

1.3、终端一:开启Swap

# 创建Swap文件$ fallocate -l 8G /mnt/swapfile# 修改权限只有根用户可以访问$ chmod 600 /mnt/swapfile# 配置Swap文件$ mkswap /mnt/swapfile# 开启Swap$ swapon /mnt/swapfile

执行free,确认Swap配置成功

$ free total used free shared buff/cache availableMem: 8169348 331668 6715972 696 1121708 7522896Swap: 8388604 0 8388604

free 输出中,Swap 空间以及剩余空间都从 0 变成了 8GB,说明 Swap 已经正常开启。

1.4、终端一:运行​​dd​​命令,模拟大文件的读取

# 写入空设备,实际上只有磁盘的读请求$ dd if=/dev/sda1 of=/dev/null bs=1G count=2048

1.5、终端二:运行​​sar​​命令,查看内存各个指标的变化情况

# 间隔1秒输出一组数据# -r表示显示内存使用情况,-S表示显示Swap使用情况$ sar -r -S 104:39:56 kbmemfree kbavail kbmemused %memused kbbuffers kbcached kbcommit %commit kbactive kbinact kbdirty04:39:57 6249676 6839824 1919632 23.50 740512 67316 1691736 10.22 815156 841868 404:39:56 kbswpfree kbswpused %swpused kbswpcad %swpcad04:39:57 8388604 0 0.00 0 0.0004:39:57 kbmemfree kbavail kbmemused %memused kbbuffers kbcached kbcommit %commit kbactive kbinact kbdirty04:39:58 6184472 6807064 1984836 24.30 772768 67380 1691736 10.22 847932 874224 2004:39:57 kbswpfree kbswpused %swpused kbswpcad %swpcad04:39:58 8388604 0 0.00 0 0.00…04:44:06 kbmemfree kbavail kbmemused %memused kbbuffers kbcached kbcommit %commit kbactive kbinact kbdirty04:44:07 152780 6525716 8016528 98.13 6530440 51316 1691736 10.22 867124 6869332 004:44:06 kbswpfree kbswpused %swpused kbswpcad %swpcad04:44:07 8384508 4096 0.05 52 1.27

可以看到,sar 的输出结果是两个表格,第一个表格表示内存的使用情况,第二个表格表示 Swap 的使用情况。其中,各个指标名称前面的 kb 前缀,表示这些指标的单位是 KB。

大部分指标已经见过,出现新的指标介绍如下:

​​​kbcommit​​,表示当前系统负载需要的内存。它实际上是为了保证系统内存不溢出,对需要内存的估计值。%commit,就是这个值相对总内存的百分比。​​kbactive​​,表示活跃内存,也就是最近使用过的内存,一般不会被系统回收。​​​kbinact​​,表示非活跃内存,也就是不常访问的内存,有可能会被系统回收。

清楚界面指标含义后,分析相关现象,可以看到,总的内存使用率(%memused)在不断增长,从开始的 23% 一直长到了 98%,并且主要内存都被缓冲区(kbbuffers)占用。

刚开始,剩余内存(kbmemfree)不断减少,而缓冲区(kbbuffers)则不断增大,由此可知,剩余内存不断分配给了缓冲区。一段时间后,剩余内存已经很小,而缓冲区占用了大部分内存。这时候,Swap 的使用开始逐渐增大,缓冲区和剩余内存则只在小范围内波动。

疑问:为什么缓冲区在不停增大?这又是哪些进程导致的呢?

1.6、终端二:按下 ​​Ctrl+C​​​ 停止 ​​sar​​​ 命令,然后运行下面的 ​​cachetop​​ 命令,观察缓存的使用情况

$ cachetop 512:28:28 Buffers MB: 6349 / Cached MB: 87 / Sort: HITS / Order: ascendingPID UID CMD HITS MISSES DIRTIES READ_HIT% WRITE_HIT% 18280 root python 22 0 0 100.0% 0.0% 18279 root dd 41088 41022 0 50.0% 50.0%

通过 cachetop 的输出,可以看到,dd 进程的读写请求只有 50% 的命中率,并且未命中的缓存页数(MISSES)为 41022(单位是页)。这说明,正是案例开始时运行的 dd,导致了缓冲区使用升高。

疑问:为什么 Swap 也跟着升高了呢?直观来说,缓冲区占了系统绝大部分内存,还属于可回收内存,内存不够用时,不应该先回收缓冲区吗?

这种情况,还得进一步通过 ​​/proc/zoneinfo​​ ,观察剩余内存、内存阈值以及匿名页和文件页的活跃情况。

1.7、终端二:按下 ​​Ctrl+C​​​,停止 ​​cachetop​​​ 命令。然后运行下面的命令,观察 ​​/proc/zoneinfo​​ 中这几个指标的变化情况

# -d 表示高亮变化的字段# -A 表示仅显示Normal行以及之后的15行输出$ watch -d grep -A 15 'Normal' /proc/zoneinfoNode 0, zone Normal pages free 21328 min 14896 low 18620 high 22344 spanned 1835008 present 1835008 managed 1796710 protection: (0, 0, 0, 0, 0) nr_free_pages 21328 nr_zone_inactive_anon 79776 nr_zone_active_anon 206854 nr_zone_inactive_file 918561 nr_zone_active_file 496695 nr_zone_unevictable 2251 nr_zone_write_pending 0

可以发现,剩余内存(pages_free)在一个小范围内不停地波动。当它小于页低阈值(pages_low) 时,又会突然增大到一个大于页高阈值(pages_high)的值。

再结合刚刚用 sar 看到的剩余内存和缓冲区的变化情况,可以推导出,剩余内存和缓冲区的波动变化,正是由于内存回收和缓存再次分配的循环往复。

当剩余内存小于页低阈值时,系统会回收一些缓存和匿名内存,使剩余内存增大。其中,缓存的回收导致 sar 中的缓冲区减小,而匿名内存的回收导致了 Swap 的使用增大。紧接着,由于 dd 还在继续,剩余内存又会重新分配给缓存,导致剩余内存减少,缓冲区增大。

现象:如果多次运行 dd 和 sar,可能会发现,在多次的循环重复中,有时候是 Swap 用得比较多,有时候 Swap 很少,反而缓冲区的波动更大。

换句话说,系统回收内存时,有时候会回收更多的文件页,有时候又回收了更多的匿名页。

显然,系统回收不同类型内存的倾向,似乎不那么明显。此时 swappiness,正是调整不同类型内存回收的配置选项。

1.8、终端二:按下 ​​Ctrl+C​​​ 停止 ​​watch​​​ 命令,然后运行下面的命令,查看 ​​swappiness​​ 的配置

$ cat /proc/sys/vm/swappiness60

swappiness 显示的是默认值 60,这是一个相对中和的配置,所以系统会根据实际运行情况,选择合适的回收类型,比如回收不活跃的匿名页,或者不活跃的文件页。

此时,已经找出了 Swap 发生的根源。另一个问题就是,刚才的 Swap 到底影响了哪些应用程序呢?换句话说,Swap 换出的是哪些进程的内存?

这里推荐 proc 文件系统,用来查看进程 Swap 换出的虚拟内存大小,它保存在 ​​/proc/pid/status​​ 中的 VmSwap 中(执行 man proc 来查询其他字段的含义)。

1.9、终端二:查看使用 Swap 最多的进程。

# 按VmSwap使用量对进程排序,输出进程名称、进程ID以及SWAP用量$ for file in /proc/*/status ; do awk '/VmSwap|Name|^Pid/{printf $2 " " $3}END{ print ""}' $file; done | sort -k 3 -n -r | headdockerd 2226 10728 kBdocker-containe 2251 8516 kBsnapd 936 4020 kBnetworkd-dispat 911 836 kBpolkitd 1004 44 kB

从这里可以看到,使用 Swap 比较多的是 dockerd 和 docker-containe 进程,所以,当 dockerd 再次访问这些换出到磁盘的内存时,也会比较慢。

这也说明了一点,虽然缓存属于可回收内存,但在类似大文件拷贝这类场景下,系统还是会用 Swap 机制来回收匿名内存,而不仅仅是回收占用绝大部分内存的文件页。

1.10、结束案例,关闭swap

$ swapoff -a

关闭 Swap 后再重新打开,也是一种常用的 Swap 空间清理方法

$ swapoff -a && swapon -a

二、总结

在内存资源紧张时,Linux 会通过 Swap ,把不常访问的匿名页换出到磁盘中,下次访问的时候再从磁盘换入到内存中来。可以设置 ​​/proc/sys/vm/min_free_kbytes​​​,来调整系统定期回收内存的阈值;也可以设置 ​​/proc/sys/vm/swappiness​​,来调整文件页和匿名页的回收倾向。

当 Swap 变高时,可以用 ​​sar​​​、​​/proc/zoneinfo​​​、​​/proc/pid/status​​ 等方法,查看系统和进程的内存使用情况,进而找出 Swap 升高的根源和受影响的进程。

反过来说,通常,降低 Swap 的使用,可以提高系统的整体性能。要怎么做呢?

禁止 Swap,现在服务器的内存足够大,所以除非有必要,禁用 Swap 就可以了。随着云计算的普及,大部分云平台中的虚拟机都默认禁止 Swap。如果实在需要用到 Swap,可以尝试降低 swappiness 的值,减少内存回收时 Swap 的使用倾向。响应延迟敏感的应用,如果它们可能在开启 Swap 的服务器中运行,你还可以用库函数 mlock() 或者 mlockall() 锁定内存,阻止它们的内存换出。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:顺心捷达单号查询API(顺心捷达单号查询单号2010751266)
下一篇:系统的Swap变高了(上)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~