宝塔php-fpm内存过高,CPU占有率过高带来的优化和调整
首先,PHP-FPM过高让CPU跑满的问题,要么是你的PHP代码有问题,要么和php-fpm 的配置有关。
我们在设置pm.max_requests之前必须先要了解php-fpm三种模式:
1、静态static
2、动态dynamic
3、按需ondemand
跟 pm.max_requests设置 有关的,只有动态dynamic模式。
dynamic:动态模式
启动进程数pm.start_servers
启动后进程数在pm.min_spare_servers和pm.max_spare_servers之间
超过pm.max_requests请求数重新生成子进程
再了解一下:
一、pm.max_requests作用是什么?
设置每个子进程重生之前服务的请求数,对于可能存在内存泄漏的第三方模块来说是非常有用的。
如果设置为 ’0′ 则一直接受请求,等同于 PHP_FCGI_MAX_REQUESTS 环境变量。

默认值: 0
pm.max_requests = 500
这段配置的意思是,当一个 PHP-CGI 进程处理的请求数累积到 500 个后,自动重启该进程。
注意:
pm.max_requests设置得太小也容易出现无进程可用(502状态),一般来说,普通网站设置max_requests 300~500 合适,但也要结合pm.start_servers和你的网站访问量来看,也可以适当调大和减少,这个是因情况而异的。
二、为什么需要重启进程呢?
一般在项目中,我们多多少少都会用到一些 PHP 的第三方库,这些第三方库经常存在内存泄漏问题,当然了,也有可能是自己写的程序代码。如果不定期重启 PHP-CGI 进程,势必造成内存使用量不断增长。因此 PHP-FPM 作为 PHP-CGI 的管理器,提供了这么一项监控功能,对请求达到指定次数的 PHP-CGI 进程进行重启,保证内存使用量不增长。
正是因为这个机制,在高并发的站点中,经常导致 502 错误,我猜测原因是 PHP-FPM 对从 NGINX 过来的请求队列没处理好。
注意:
有时候由于 php-fpm 有好多闲置的进程一直不释放, 导致内存占用过大,FastCGI 进程一旦加载就不会释放,当其工作完成后,就休眠于 FastCGI 系统池中,等待下一次被唤醒。甚至是php-fpm假死,也会出现502的错误,只能重启php-fpm才能解决这个问题。
例如:Nginx报错upstream timed out (110: Connection timed out) 就是由于pm.max_requests 默认值为0,没有重启所引起的。
目前我们的解决方法是,把这个值尽量设置大些,尽可能减少 PHP-CGI 重新 SPAWN 的次数,同时也能提高总体性能。在我们自己实际的生产环境中发现,内存泄漏并不明显,因此我们将这个值可以设置得非常大。
如果pm.max_requests没有设置重启参数,默认为0不限制最大服务次数,也就是子进程永远不重启,经验表明,长时间不重启子进程会导致系统负载异常,处理时间变长等现象。
总结:
pm.max_requests究竟设置多大?大家要根据自己的实际情况来设置这个值,例如我设置的(204800)不能盲目地加大或设置过小。如果你设置过小,有可能会造成“php-fpm占用cpu和内存过高100% ”。有时候设置为0,时间久了,占的内存就大了,还一直不释放,如果遇到请求任务过多,处理不过来,还会造成php-fpm子进程假死的情况,那时候就会经常出现502 Bad Gateway的错误,以及你打开.php的文件总是感觉很慢,请求php文件一直处于pending状态。
既然说到了php-fpm 的配置,那么就得好好的说下php-fpm 的 process management
php-fpm 的process management 有两种工作方式,一种是static, 一种是dynamic, 对于小的cloud 或者vps 一般用static,但是其实大部分时间我们都在使用dynamic
pm = dynamic
pm.max_children = 160
pm.start_servers = 20
pm.min_spare_servers = 20
pm.max_spare_servers = 40
和process management 有直接关系的是这四个参数, pm.max_children 在pm=static 的时候有用,在pm = dynamic 的时候, 剩下三个参数才开始起作用。
这里问题的关键在于,如何设置pm.max_children 的值。
对于不同的php application,每个php-fpm instance 占用的内存也不一样,需要具体application 具体分析,但是这里我们可以去个average , 30M
假设你的服务器有8G的内存,其中的6GB 可以划给php-fpm, 那么
pm.max_children = 6000MB / 30MB =200
也就是说在这种情况下,200这个值是比较合适的. 这里需要注意的是,赋予max_children 一个很高的值,并不代表会带来高性能,也许会拖垮整个服务器,剩下的三个参数,按照实际情况,设置的差不多就行了。


可以用如下的命令来实际查看一下single php-fpm usage:
ps --no-headers -o "rss,cmd" -C php-fpm | awk '{ sum+=$1 } END { printf ("%d%s\n", sum/NR/1024,"M") }';另外别忘了开启php-fpm 的 slowlog,这样方便你以后查看日志来进行debug:
slowlog = /usr/local/php/var/log/slow.log
对于CPU 占有率过高的问题,这个其实并不是php-fpm 的问题,而是你写的php 代码的问题,这个时候可以通过设置pm.status_path 开查看到底是哪个php application 占用的cpu 资源。
链接:https://www.jin-you.com/news/1281.html
