OKXUN管理的一台Debian服务器因为安装的是最新Drupal网站管理系统,对内存要求远高于WordPress、帝国cms等轻量级cms,总是出现内存被占满、502错误的问题,而CPU的占用却很低,检查一番之后发现是非常典型的配置不当导致的资源耗尽。如果你用的也是配置很低的VPS Linux服务器,出现了内存占满,卡顿、502错误的问题,那么赶紧按本文的办法去处理,效果立竿见影。
首先,咱们不能瞎搞,先查一下是不是apache和php-fpm把内存消耗占尽了,运行以下命令就可以给你的服务器内存占用算个总账:
ps aux | awk '{print $11, $6/1024}' | sort -k2 -rn | head -n 20 | awk '{arr[$1]+=$2} END {for (i in arr) {print i, arr[i]}}' | sort -k2 -rn
输出怎么看:
apache2:如果这个总和超过 500MB,对于2G服务器来说绝对是配置问题。
php-fpm8.5:如果这个很高,说明pm.max_children设置太多,或者Drupal某个页面有内存泄漏。
mariadbd:它高,就是数据库占用了。
然后,查并发连接数,看看当前有多少人连着你的服务器:
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
ESTABLISHED: 正常情况下,一个小站几十个就算多了。如果你看到成百上千个 ESTABLISHED,那可能是被大量并发请求(比如恶意爬虫)。
TIME_WAIT: 如果这个数值特别高(几千),说明有大量的短连接请求。
最后,看看是不是某个 IP 在疯狂请求(查 IP 排名):
awk '{print $1}' /var/log/apache2/okxun-com-access.log | sort | uniq -c | sort -nr | head -n 10
(这里第个网站日志名称都可能不一样,按自己的改)
判断: 如果第一名的 IP 请求数是几千次,且不是你自己的 IP 或 Google、Bing、百度等搜索爬虫,那大概率是恶意采集或攻击。
对策: 把这个IP扔进Fail2Ban的黑名单,或者直接用iptables封掉。
okxun.com的服务器通过检查发现,没有攻击,是PHP-FPM在“空转”吃内存,PHP-FPM进程池里养了一大堆空闲进程,它们即使没有活干,也霸占着内存不释放。
解决方案:开启“按需分配”模式
1、编辑配置文件
找到PHP 8.5的www.conf配置文件,根据你的版本,路径通常是:/etc/php/8.5/fpm/pool.d/www.conf (如果找不到,试试 /etc/php/php-fpm.d/www.conf 或者用find /etc -name www.conf找)
vi /etc/php/8.5/fpm/pool.d/www.conf
2. 修改关键参数
找到以下参数,并按如下数值修改。原来的值前面如果有分号 ;,记得把分号去掉让它生效。
A. 修改进程管理模式 (关键) 默认通常是dynamic(动态),这对小内存服务器是灾难。一定要改为ondemand。
pm = ondemand
B. 限制最大进程数,你现在可能有20-30个进程在跑(或者只有5个也不行),我们要自己指定。
pm.max_children = 12
解释:2G内存,扣掉系统和数据库,留给PHP的大概800M。
Drupal 11比较吃内存,一个进程按60-80M算,10-12个是安全线。
C. 缩短空闲销毁时间,这是ondemand模式的神技。没请求时,多久杀掉进程?
pm.process_idle_timeout = 10s
默认通常是10s,但前面的;号没有删除启用,建议改为5s或启用保持10s。
意味着如果10秒没人访问,PHP进程就会释放内存,降到0个进程。
D. 预防内存泄漏,为了防止PHP 8.5或Drupal模块有内存泄漏,让进程处理一定数量请求后强制重启。
pm.max_requests = 200
3. 保存并重启,重启PHP-FPM服务:systemctl restart php8.5-fpm
(如果不确定服务名,可以用systemctl restart php*fpm)
最后考验技术的时候到了,重启完只需等待10-20秒,再次运行计算内存的命令,验证效果:
ps aux | awk '{print $11, $6/1024}' | sort -k2 -rn | head -n 20 | awk '{arr[$1]+=$2} END {for (i in arr) {print i, arr[i]}}' | sort -k2 -rn
预期结果: 你现在应该会看到php-fpm的占用大幅下降(可能降到几十MB,甚至0MB,取决于刚才有没有人访问),502错误问题解决。(文/okxun.com,禁止复制转载。)
更新:如果你的服务器通过上面的操作还是出现502错误,请按下面增加设置:
第一步、修改php.ini,增加修改以下设置;
vi /etc/php/8.5/fpm/php.ini
memory_limit = 512M
max_execution_time = 300
重启PHP-FPM,修改php.ini必须重启服务才能生效
systemctl restart php8.5-fpm
第二步、修改Apache的超时设置
vi /etc/apache2/apache2.conf
# 全局超时时间,默认可能是300,但有时候会被重置
Timeout 300
# 专门针对代理请求(PHP-FPM)的超时时间,这一行非常关键,很多时候默认是60秒 ProxyTimeout 300
重启Apache:systemctl restart apache2
PS:对于Drupal这种大型系统,安装模块、清除缓存等操作,请直接在SSH终端里用Drush指令,它绕过了Apache,直接在系统底层运行,速度快、稳如老狗、永远不会502。
# 进入你的网站目录
cd /var/www/html
# 这里的 cr = Cache Rebuild (重建缓存)
vendor/bin/drush cr
评论