任务
网站最初运行良好,但随着时间的推移出现了崩溃。长时间无法访问,阿里云发来告警短信、邮件,两次出击分别处理CPU占用高与内存占用高问题。
虚拟内存
这个是最初遇到的问题,因为在配置RSSHub:快速整合资源设置了虚拟内存以便解决下载中断问题,但此后频繁发生了CPU过高的问题。

究其原因,使用top指令,查看CPU占用高的进程,发现名为kswap0的进程占用了93.7%!
linux top命令VIRT,RES,SHR,DATA的含义
VIRT:virtual memory usage 虚拟内存
- 进程“需要的”虚拟内存大小,包括进程使用的库、代码、数据等
- 假如进程申请100m的内存,但实际只使用了10m,那么它会增长100m,而不是实际的使用量
RES:resident memory usage 常驻内存
- 进程当前使用的内存大小,但不包括swap out
- 包含其他进程的共享
- 如果申请100m的内存,实际使用10m,它只增长10m,与VIRT相反
- 关于库占用内存的情况,它只统计加载的库文件所占内存大小
SHR:shared memory 共享内存
- 除了自身进程的共享内存,也包括其他进程的共享内存
- 虽然进程只使用了几个共享库的函数,但它包含了整个共享库的大小
- 计算某个进程所占的物理内存大小公式:RES – SHR
- swap out后,它将会降下来
kswapd0
当然要搜索kswapd0它是何方神圣,不过名中内嵌的swap让人猜测大概:
kswapd0进程的作用:
它是虚拟内存管理中,负责换页的,操作系统每过一定时间就会唤醒kswapd ,看看内存是否紧张,如果不紧张,则睡眠,在 kswapd 中,有2 个阀值,pages_hige 和 pages_low,当空闲内存页的数量低于 pages_low 的时候,kswapd进程就会扫描内存并且每次释放出32 个free pages,直到 free page 的数量到达pages_high。
Linux设置大内存页解决kswapd0进程过渡消耗CPU的问题
更直接的表述如下:
- swap分区的作用是当物理内存不足时,会将一部分硬盘当做虚拟内存来使用。
- kswapd0 占用过高是因为 物理内存不足,使用swap分区与内存换页操作交换数据,导致CPU占用过高。
上面文章提供一种解决方案是设置大内存页,以减少换页的频率,当然我这里就直接将扩展的虚拟内存删除,以绝后患。
$ rm -rf /var/swapfile
(这里的swapfile是之前设置的虚拟内存文件名)
$ df -h
php-fpm
还让人警惕的是服务器的内存占用依然很高,top命令后,输入M(shift+m)即可得到按内存占用率排序的进程。
可见php-fpm占据榜单大部,而重启php-fpm服务后,内存就得到了释放,因此需要在这里做文章。
那先了解一下php-fpm是什么
PHP-FPM(FastCGI Process Manager)是一个PHPFastCGI管理器,提供了进程管理的功能。
进程包含 master 进程和 worker 进程两种进程。 master 进程只有一个,负责监听端口,接收来自 Web Server 的请求,而 worker 进程则一般有多个(具体数量根据实际需要配置), 每个进程内部都嵌入了一个 PHP 解释器,是 PHP 代码真正执行的地方。
来自 <php-fpm-百度百科> <Nginx+PHP-FPM运行原理>
配置文件
参考文章:Linux的php-fpm优化心得-php-fpm进程占用内存大和不释放内存问题(转)
本机的配置文件为/etc/php-fpm.d/目录下的www.conf文件,具体的文件详情可以参考文章php-fpm配置文件详解。
在阅读文章后,根据服务器1G的内存大小,只修改子进程的最大数量,把最大子进程数pm.max_children改为15与最大空闲子进程数pm.max_spare_servers改为 15
; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand'
; Note: This value is mandatory.
; 同一时刻能够存活的最大子进程的数量
pm.max_children = 15 #50
; The number of child processes created on startup.
; Note: Used only when pm is set to 'dynamic'
; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2
pm.start_servers = 5
; The desired minimum number of idle server processes.
; Note: Used only when pm is set to 'dynamic'
; Note: Mandatory when pm is set to 'dynamic'
pm.min_spare_servers = 5
; The desired maximum number of idle server processes.
; Note: Used only when pm is set to 'dynamic'
; Note: Mandatory when pm is set to 'dynamic'
; 最大空闲子进程数量,空闲子进程数量超过这个值,那么相应的子进程会被杀掉。
pm.max_spare_servers = 15 # 35
效果展示
此时php-fpm的进程数就龟缩为7、8个,而按照每个进程大约占用40-60M的内存空间,共计占用约400M,可以承载。
目前的free命令查看占用结果,available为1.1G,远高于之前的319M,再经过一段时间继续验证有效性。