先把当时的情况摆出来。一台 4 核 8G 的 CentOS 7.9 跑 Apache 2.4 加 mod_php,平时没事,一到晚上采集任务并发上来,free 里可用内存掉到几十 M,vmstat 显示 si so 一直不为零,机箱风扇都响起来了。

原因不止一个,得分开看。每个 Apache 进程带着 mod_php 常驻七八十 M,乘上几百个进程远超物理内存。少数情况下是进程数按 CPU 核数随手定,从没按内存反推过上限。

还有一种情况,采集任务里有大量图片处理,临时缓冲区让单进程峰值再翻一倍。另外,swap 一开就把内存页往外换,醒来时磁盘随机读把响应拖到秒级。

先统计子进程实际占了多少常驻内存

ps --no-headers -o rss -C httpd | awk '{s+=$1} END {print s/1024 " MB"}'

接着用名义内存反推能开多少进程

ps -ylC httpd --sort:rss | awk 'NR>1{print $8}' | sort -n | tail -1

然后按内存把并发上限压下来

sed -i 's/^MaxRequestWorkers.*/MaxRequestWorkers 128/' /etc/httpd/conf.modules.d/00-mpm.conf && systemctl reload httpd

剩下的就是确认换页是否停下来

vmstat 1 3 && free -m

恢复的判定其实很直接。free 的 available 保持在 1G 以上,vmstat 里 si so 归零,Apache 子进程总数稳定在一百三十以内,夜间采集任务的耗时回到十分钟左右。

这里还有个坑。压并发会让高峰请求排队,要配合把采集任务错峰;swap 不是不能用,但被换出去的进程醒来的那一下延迟很难看。监控比日志更早给出信号,事后回看经常能提前半小时发现异常。

作者 9823189