Linux的php-fpm优化心得-php-fpm进程占用内存大和不释放内存问题

最近发现博客的内存老是隔三差五地被“吃掉”了,登录到后台后偶尔会出卡顿的情况,一开始怀疑是Swap不够导致的,于是给VPS主机增加了几个G的Swap,观察了一段时间后发现再大的Swap也被慢慢地“吃掉”了!

很显然是PHP某些服务一直在占用着VPS的内存没有释放,导致物理内存耗尽后调用了Swap,显然Swap没有物理内存运行的效率高,于是就出现了进程卡死的情况了。考虑到挖站否现在用的Wordpress用的主题与插件过多,出现这样的情况也是正常。

LNMP架构中PHP是运行在FastCGI模式下,按照官方的说法,php-cgi会在每个请求结束的时候会回收脚本使用的全部内存,但是并不会释放给操作系统,而是继续持有以应对下一次PHP请求。而php-fpm是FastCGI进程管理器,用于控制php的内存和进程等。

Linux的php-fpm优化心得-php-fpm进程占用内存大和不释放内存

所以,解决的办法就是通过php-fpm优化总的进程数和单个进程占用的内存,从而解决php-fpm进程占用内存大和不释放内存的问题。更多的Linux服务器优化方法以及建站心得,还有:

  1. Linux Crontab命令定时任务基本语法与操作教程-VPS/服务器自动化
  2. 阿里云日本VPS主机速度性能评测-日本软银SoftBank\香港NTT线路
  3. DNS域名解析启用DNSSEC防止DNS劫持-Google Cloud DNS设置DNSSEC

PS:2018年12月14日更新,如果你的VPS主机的内存和性能不是很好的话,这时最好是启用缓存可以大大节省资源消耗:WordPress开启Nginx fastcgi_cache缓存加速方法-Nginx配置实例

PS:2019年9月29日更新,由于Google主导开发的服务器优化神器ngx_pagespeed,集成了图片延迟加载、自适应webp、JS和CSS优化、图片优化等一整套优化工具:PageSpeed服务器优化神器-Nginx部署ngx_pagespeed模块和加速效果体验

一、分析判断php-fpm内存占用情况

如果你发现VPS主机出现了卡顿的情况,首先查看一下内存的占用情况,常用的命令就是Top、Glances、Free等,不了解这些命令的朋友可以先看看挖站否做的专题:Linux系统监控命令整理汇总-掌握CPU,内存,磁盘IO等找出性能瓶颈

使用Glances命令,再按下m,就可以查看到当前VPS主机进程内存占用情况了,按照占用内存由多到少排序(或者使用Top命令,按下M,效果是一样的)。如下图(点击放大):

php-fpm内存占用情况

这是一张重启后进程内存占用情况图,从前后对比中可以发现:随着开机时间的增长,php-fpm占用的内存越来越大,最终php-fpm耗尽了VPS所有物理内存。

php-fpm重启后内存

查看当前php-fpm总进程数,命令:ps -ylC php-fpm --sort:rss。其中RSS就是占用的内存情况。如下图:

php-fpm进程总数

查看当前php-fpm进程的内存占用情况及启动时间,命令如下:

ps -e -o 'pid,comm,args,pcpu,rsz,vsz,stime,user,uid'|grep www|sort -nrk5

从下图可以看出当前php-fpm所有进程平均每个进程占用了60-70MB的内存,启动时间,是当天的话就是3:12,否则会显示是X月X日。

php-fpm启动时间

查看当前php-fpm进程平均占用内存情况,一般来说一个php-fpm进程占用的内存为30-40MB,本次查询的结果是60MB,显然是多了。命令如下:

ps --no-headers -o "rss,cmd" -C php-fpm | awk '{ sum+=$1 } END { printf ("%d%s\n", sum/NR/1024,"M") }'
结果61M

二、熟悉php-fpm配置文件说明

php-fpm.conf就是php-fpm的配置文件,路径一般在:/usr/local/php/etc,如下图:

php-fpm配置路径

php-fpm.conf几个重要的参数说明如下:

pm = dynamic #指定进程管理方式,有3种可供选择:static、dynamic和ondemand。
pm.max_children = 16 #static模式下创建的子进程数或dynamic模式下同一时刻允许最大的php-fpm子进程数量。
pm.start_servers = 10 #动态方式下的起始php-fpm进程数量。
pm.min_spare_servers = 8 #动态方式下服务器空闲时最小php-fpm进程数量。
pm.max_spare_servers = 16 #动态方式下服务器空闲时最大php-fpm进程数量。
pm.max_requests = 2000 #php-fpm子进程能处理的最大请求数。
pm.process_idle_timeout = 10s
request_terminate_timeout = 120

pm三种进程管理模式说明如下:

pm = static,始终保持一个固定数量的子进程,这个数由pm.max_children定义,这种方式很不灵活,也通常不是默认的。

pm = dynamic,启动时会产生固定数量的子进程(由pm.start_servers控制)可以理解成最小子进程数,而最大子进程数则由pm.max_children去控制,子进程数会在最大和最小数范围中变化。闲置的子进程数还可以由另2个配置控制,分别是pm.min_spare_servers和pm.max_spare_servers。如果闲置的子进程超出了pm.max_spare_servers,则会被杀掉。小于pm.min_spare_servers则会启动进程(注意,pm.max_spare_servers应小于pm.max_children)。

pm = ondemand,这种模式和pm = dynamic相反,把内存放在第一位,每个闲置进程在持续闲置了pm.process_idle_timeout秒后就会被杀掉,如果服务器长时间没有请求,就只会有一个php-fpm主进程。弊端是遇到高峰期或者如果pm.process_idle_timeout的值太短的话,容易出现504 Gateway Time-out错误,因此pm = dynamic和pm = ondemand谁更适合视实际情况而定。

三、解决php-fpm进程占用内存大问题

3.1  调整管理模式

static管理模式适合比较大内存的服务器,而dynamic则适合小内存的服务器,你可以设置一个pm.min_spare_servers和pm.max_spare_servers合理范围,这样进程数会不断变动。ondemand模式则更加适合微小内存,例如512MB或者256MB内存,以及对可用性要求不高的环境。

php-fpm调整管理模式

3.2  减少php-fpm进程数

如果你的VPS主机的内存被占用耗尽,可以检查一下你的php-fpm进程数,按照php-fpm进程数=内存/2/30来计算,1GB内存适合的php-fpm进程数为10-20之间,具体还得根据你的PHP加载的附加组件有关系。

Linux的php-fpm加载情况

3.3  php-fpm配置示例

这里以1GB内存的VPS配置php-fpm为演示,实际操作来看设置数值还得根据服务器本身的性能、PHP等综合考虑。

pm = dynamic #dynamic和ondemand适合小内存。
pm.max_children = 15 #static模式下生效,dynamic不生效。
pm.start_servers = 8 #dynamic模式下开机的进程数量。
pm.min_spare_servers = 6 #dynamic模式下最小php-fpm进程数量。
pm.max_spare_servers = 15 #dynamic模式下最大php-fpm进程数量。

四、解决php-fpm进程不释放内存问题

上面通过减少php-fpm进程总数来达到减少php-fpm内存占用的问题,实际使用过程中发现php-fpm进程还存长期占用内存而不释放的问题。解决的方法就是减少pm.max_requests数。

php-fpm减少进程数

最大请求数max_requests,即当一个 PHP-CGI 进程处理的请求数累积到 max_requests 个后,自动重启该进程,这样达到了释放内存的目的了。以1GB内存的VPS主机设置为例(如果你设置的数值没有达到释放内存可以继续调低):

pm.max_requests = 500 

php-fpm释放内存

当php-fpm进程达到了pm.max_requests设定的数值后,就会重启该进程,从而释放内存。下图是我测试后的效果,可以看出php-fpm进程被强制结束并释放了内存。

php-fpm重启进程释放内存

五、总结

对于大内存以及对并发和可用性要求的话,建议使用static管理模式+最大的pm.max_children。如果是小内存的服务器,建议使用dynamic或者ondemand模式,同时降低pm.start_servers和pm.max_spare_servers进程数。

为什么我调整了参数没有达到应有的效果?根据wzfou.com的经验,php-fpm配置文件参数不能一概而论,必须要结合服务器自身的性能、WEB动态内容以及对可用性的要求来进行调整,内存长期占用最好是再检查一下是否有内存泄露。

2019年10月9日更新,如果你的php-fpm参数调整得过小,有可能出现502错误,解决办法:解决WordPress后台编辑保存菜单出现502错误

文章出自:挖站否 https://wzfou.com/php-fpm/,版权所有。本站文章除注明出处外,皆为作者原创文章,可自由引用,但请注明来源。


分享到:
Avatar for Qi
关于站长(Qi),2008年开始混迹于免费资源圈中,有幸结识了不少的草根站长。之后自己摸爬滚打潜心学习Web服务器、VPS、域名等,兴趣广泛,杂而不精,但愿将自己经验与心得分享出来与大家共勉。
已有 35 条评论
  1. Avatar for Edi Edi

    QI大,我的单个php-fpm进程平均占用达到了247M….8G的VPS,这个是不是太大了点啊,是不是需要调低pm.max_requests啊?

    2019年11月4日 23:20 回复
    • Avatar for Qi Qi

      8GB的话,如果负载低的话可以不用调,足够用了。

      2019年11月7日 08:121 回复
  2. 这段时间也被这个内存一直不释放困扰,最近几天想着好好优化一下,包括网站主题和各种代码bug,在使用php缓存和数据库对象缓存的情况下,内存不再过山车,但是一直不断爬升,直到用完为止。今天百度到Qi的文章,试试添加个最大请求数看下,不知道效果会如何

    2019年10月4日 15:561 回复
    • Avatar for Qi Qi

      可以试试,我现在的情况好多了。

      2019年10月4日 16:04 回复
      • [太开心]一个多小时过去了,效果很显著,感谢!

        2019年10月4日 17:47 回复
  3. Avatar for zumenbo zumenbo

    我的VPS用了宝塔面板,经常发现CPU跟内存占用都不高,但系统负载一直飙高,网页打开也比较慢。不知道是什么问题

    2018年8月18日 14:29 回复
    • Avatar for Qi Qi

      那看看磁盘IO读写是不是占满了,另外看看iowait是不是达到了百分几十了,一般是百分一或者0

      2018年8月18日 14:40 回复
      • Avatar for zumenbo zumenbo

        连上%,输入什么命令都没有反应了。

        2018年8月19日 20:53 回复
        • Avatar for Qi Qi

          那应该是死机了。这种情况可以重启的时候持续观察,把一段时间的日志也下载下来,看看是不是有一些异常的IP,我以前也遇到这样的情况,基本上都是判定攻击了。

          2018年8月20日 00:38 回复
  4. 最新新购了一台经典CN2 GIA,查IP段和qi总的在同一个C段 😀 想问问qi总所用的操作系统、php版本和WP优化插件,准备一模一样地配一台

    2018年8月11日 11:34 回复
    • Avatar for Qi Qi

      我也购买了一台1GB的。现在用的操作系统是Ubuntu 18,PHP用的是7.1,感觉可能用7.2也不错,wp优化插件现在用的是redis插件,用来数据库加速。

      2018年8月11日 14:26 回复
      • 之前配php7.2+mariadb10.3奇慢无比,也不知道是什么情况,现在我重新配成了debian9+php7.1+mariadb5.5(感觉debian会比ubuntu稳定),缓存用的是memcached配上W3 Total Cache(这个插件真的很强大,已经不用wp super cache了)。qi来测测速度怎么样?https://www.equestriacn.com/

        2018年8月11日 16:59 回复
  5. Avatar for Ken Ken

    我的是php-cgi占用CPU过多. 内存占用不大. 请问是同样的配置么?

    2018年7月25日 17:59 回复
    • Avatar for Qi Qi

      是的,也是WP吗?如果是WP的话,建议检查一下是不是有没有插件长期占用CPU,或者是进程。试着通过调整参数看看能不能释放。

      2018年7月26日 09:19 回复
  6. 出现牛顿?不是卡顿嘛?

    2018年7月17日 10:40 回复
    • Avatar for Qi Qi

      哈哈,已经更新。

      2018年7月17日 10:46 回复
  7. 感觉对wordpress无爱了

    2018年7月15日 09:25来自移动端 回复
    • 为何?
      WordPressCMS不是挺便利的吗?

      2018年7月16日 08:45 回复
  8. Avatar for c c

    自己写博客系统就是方便,每个函数用完都注销掉,内存畅爽无卡顿

    2018年7月13日 07:23 回复
    • Avatar for Qi Qi

      这样很吊。

      2018年7月13日 20:51 回复
  9. Avatar for baoang baoang

    站长用的lnmp.org的还是oneinstack一键包?我记得是后者?
    我自己目前改成ondemand了,但效果也不行,物理内存过小。不过,依稀记得在哪里见过一个公式用来计算动态模式下那几个什么pm.max之类的数量计算。

    2018年7月12日 20:38 回复
    • Avatar for Qi Qi

      是的,用的oneinstack。有一个计算工具,但是我用了之后感觉还得根据自己的服务器配置还有PHP、Ningx等配置还自己调整,我的经验就是调整pm.max_requests,目前来看有效果了,你可以试着将pm.max_requests调小,然后看看最后的效果。

      2018年7月12日 21:48 回复
      • Avatar for baoang baoang

        多谢。
        这个内存和效率吧,说到底最简单的,还是加一个字。8G干不了的,双倍一下,16G就能应付。可惜我还停留在512MB上。

        2018年7月12日 23:59 回复
        • Avatar for Qi Qi

          优化的效果不如#一倍的内存。

          2018年7月13日 20:51 回复
  10. Avatar for 我觉得海星 我觉得海星

    这个用宝塔的话,可以直接做限制~

    2018年7月12日 12:13 回复
    • Avatar for Qi Qi

      用面板还是挺方便的。

      2018年7月12日 12:46 回复
  11. 自从用了宝塔面板之后,直接选择了

    2018年7月12日 11:15 回复
  12. Avatar for Now Now

    LNMP脚本优化得不错。

    2018年7月12日 09:39 回复
  13. 看不懂,一直默认,没毛病

    2018年7月11日 22:56 回复
  14. WordPress 站这么高占用么,看来我给站点分了8G内存怕不够了

    2018年7月11日 20:25 回复
    • Avatar for Qi Qi

      8GB还是很流畅的,主要是我安装的插件比较多。

      2018年7月12日 12:50 回复
  15. 沙发~

    2018年7月11日 20:23 回复
  16. Avatar for nw nw

    占个沙发。

    2018年7月11日 20:18 回复

Login

Welcome! Login in to your account

Remember me Lost your password?

Don't have account. Register

Lost Password

Register