Linux 内存控制策略

Linux 服务器在内存被消耗枯竭的时候,会导致服务器死锁无响应甚至崩溃。本文提供一些基本思路以及具体的操作命令来管理服务器内存,以防止服务器因内存不足而导致的死锁和崩溃。

进程内存使用限制

首先,我们可以查看服务器中的进程,看哪些进程是主要的内存占用大户,设置进程对内存的使用量,一旦超过我们预设的值,就将进程杀死重启。以下针对 SystemD 和 Docker 两个主要的平台说明设置方法。

值得注意的是,这个方法只能限制单一的进程的内存占用量。如果进程数量过多,且每一个进程对内存的需求都不小的情况下,仍然是需要考虑添加系统的内存,或者使用后面讲到的如何使用 Swap 文件来将内存的数据临时交换到 Swap 文件中。

SystemD

Service 一栏里添加,比如这个进程最大内存使用为 8GB,若超过就会引发 OOM(Out of memory) 错误,然后进程被杀死然后重启。

[Service]
MemoryMax=8G

Docker

同 SystemD 一样,但是内存限制的指令写在命令行里,使用 --memory=8g 来限制。

ExecStart=/usr/bin/docker run --rm \
  --memory=8g \
  ...

建立 Swap

你可以为系统挂载一个 Swap 文件,当内存紧张时,Linux 系统会将一些内存中的数据移到这个 Swap 文件中,这样系统就不会因为内存不足而死锁甚至崩溃。

这个 Swap 文件的大小建议是当前设备内存的一半,最多与当前的设备内存大小一致。例如,当前的设备内存为 16GB,那么你可以创建并挂载一个 8GB 的 Swap 文件。但是这个 Swap 文件的大小没有那么重要,重要的是后面讲的关于 Swap 内存的使用策略参数 Swappiness。

创建文件和挂载

创建一个空的文件

确保当前的系统磁盘中有足够的空间来创建 Swap 文件,然后执行下方的命令来创建 Swap 文件。

# 使用 fallocate 来创建一个 8GB 大小的空文件,并将文件保存至 /swapfile
sudo fallocate -l 8G /swapfile

# 若 fallocate 在当前系统中没有,那可以使用传统的 dd 命令,该命令的效果与上面一致
sudo dd if=/dev/zero of=/swapfile bs=1G count=8

设置文件的权限

Swap 文件的权限必须是 600

# 将 swapfile 的权限设置为 600
sudo chmod 600 /swapfile

初始化文件格式

需要使用 mkswap 命令将这个文件初始化成为系统可认的 Swap 文件的格式。

sudo mkswap /swapfile

在系统中直接挂载该 Swap 文件

执行完下面的命令后,当前的系统就会在内存不够的时候开始使用这个 Swap 文件进行内存交换了,执行完后可以再使用 free -h 来查看是否有相关的 Swap 的信息。

sudo swapon /swapfile

系统启动后自动挂载

使用 swapon 命令后挂载的 Swap 文件在系统重启后就会失效,如果想让系统启动后自动挂载 Swap 文件,则需要编辑 /etc/fstab 文件,在文件最后添加上一行:

/swapfile none swap sw 0 0

Swappiness

Swappiness 其实是挺重要的一个参数,它控制 Linux 内核在内存紧张的时候倾向于使用 Swap 还是 Page cache。通俗一点来说,就是你希望系统里 Swap 文件被使用的频率是高还是低?这个值的范围一般是在 1-100 ,系统默认该值为 60 。该值越大,表示越倾向于使用 Swap 文件。

一开始没有对这个值进行设置的时候,系统在内存使用高峰的时候会变得非常慢,磁盘 IO 满载,但是 CPU 几乎停滞,自己写的服务的某些功能也变得奇慢无比,不是死锁,不是没有响应,而是非常非常的慢。这是因为,系统内存不足的时候就把内存的信息 swap out 到 Swap 文件里。当有需要时,再把相关的数据 swap in 回内存。但是 Swap 文件毕竟是存储在磁盘上,而磁盘的访问速度要远低于内存。所以频繁使用 Swap 文件做为内存数据存储中介,会严重拖慢整个系统的运行速度。

设置 Swappiness 的值,从 60 变成 10 或者更低的 1 可以有效地解决这个问题。让系统不要轻易地使用 Swap 文件来存储内存中可能放不下的数据,从而减少 Swap 文件的使用频率以提升系统的反应速度。

如何查看当前的 swappiness 的值?

使用以下的命令来查看:

cat /proc/sys/vm/swappiness

临时改变 swappiness 的值,这个改变重启后失效:

sudo sysctl vm.swappiness=10

永久地改变 swappiness 的值,这个改变重启后仍然有效:

echo 'vm.swappiness=10' | sudo tee /etc/sysctl.d/99-swappiness.conf

监控

我怎么知道当前的 Swap 文件的具体运作情况呢?

Linux 内核把内存中的数据存储到 Swap 文件中的操作,叫做 swap out,而把 Swap 文件中的数据放回到内存中的操作叫做 swap in

使用 sar 命令可以查看当前系统对 Swap 文件的操作。sar 是 System Activity Reporter 的缩写,用于报告系统当前的活动情况。

# -W 表示报告 Swap and paging 信息,3 表示每隔 3 秒报告一次
sar -W 3

若系统是稳定的状态,通常这两个值都应该是 0 或者是偶尔 in/out,如果有大量的持续的 swap inswap out,那就说明当前系统的数据在频繁地做内存到 Swap 的交换。这时你就需要考虑降低某些进程对内存的使用量,或为系统添加新的内存甚至将不同的进程运行到不同的服务器上。

总结

以上的手段只是提升系统的自适应能力,以及添加了一个缓冲层。这些手段都只是用于防止内存不足而导致服务器停滞或者崩溃。但如果服务器内存非常紧张,那么最应该做的事情仍然是添加系统内存。

This article was written by matthew

发表回复

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