一、问题现象
二、项目背景
- 线上web服务是nginx+php7+mysql
- 线上服务器配置:8核16G
-
php-fpm配置:
pm = static pm.max_children = 500 ;pm.max_requests = 5000 //此配置没有打开
三、内存持续增高原因分析
- 查看了php-fpm相关配置后,发现系统是静态机制,并且没有配置max_requests项,没有退出机制
- php进程长期存在导致内存积压无法释放,所以内存消耗持续升高
-
nginx+php-fpm运行原理?【https://juejin.im/post/58db7d...】
cgi、fast-cgi、php-fpm之间的关系? 我的理解: 1.webserver最开始只能处理静态请求,后来出现了动态请求,比如php程序,然而webserver是无法处理php程序的,这个是时候怎么办? 2.交给php解释器来处理动态php请求 3.那么webserver可以将动态请求交给php解释器处理,那么webserver如何与php解释器进行通信呢?【webserver就是nginx/apache】 4.这个时候就出现了cgi,cgi协议就是webserver和php解释器进行通信的协议 5.webserver在每次请求过来都会fork一个cgi进程进行处理,处理完成后返回,如果有10k请求,那么就fork 10k个进程,显然对系统资源很浪费 6.这时对cgi做了优化,出现了fast-cgi,fast-cgi在请求处理完成后不会直接kill掉这个进程,而是继续保留请求下一次请求,这样一个进程就能处理多个请求,不用每次都fork进程减少了系统资源浪费 7.而php-fpm就是fast-cgi的实现,并且提供了进程管理的功能,包含master和worker两种类型的进程 8.master进程只负责监听端口,接收来自webserver的请求,worker进程有多个,每个worker进程内部都嵌入了一个php解释器,是php代码真正执行的地方
-
一些php-fpm参数理解:
pm = dynamic # 三种类型选择,static/dynamic/ondemand pm.max_children = 5 # php-fpm的worker进程最大数量 pm.start_servers = 3 # php-fpm启动时候,启动的worker数量 pm.min_spare_servers = 2 # php-fpm最小空闲进程数量,每时每刻最少也有2个是空闲的进程 pm.max_spare_servers = 4 # php-fpm最大的空闲进程数量 pm.max_requests = 200 # 单个进程处理请求数量达到200就会kill掉该进程重启,进程一直存活容易发生内存泄漏
四、解决方案
- 通过现在php-fpm的配置可以得知,php-fpm没有设置max_requests,代表进程一直不会退出,每个请求完成后php-cgi会回收内存,但是不会释放给操作系统,所以大量内存被php-cgi占用。
- 官方的解决办法就是降低PHP_FCGI_MAX_REQUESTS的值,对应php-fpm配置中的max_requests
-
所以,只要重新设置 max_requests 的值,让进程达到这个值后自动重启释放内存即可
# php-fpm.conf配置 pm = static pm.max_children = 500 pm.start.servers = 100 pm.min_spare_servers = 20 pm.max_spare_servers = 100 pm.max_requests = 2000
-
修改完配置后对php-fpm进行重启
//查询当前fpm的master进程号 ps aux|grep php-fpm | grep master //平滑重启fpm,42891是master进程号 kill -USR2 42891 //立即终止fpm kill -QUIT 42891 //查看状态 ps aux|grep php-fpm //备注: php 5.3.3 以后的php-fpm 不再支持 php-fpm 以前具有的 /usr/local/php/sbin/php-fpm (start|stop|reload)等命令,所以不要再看这种老掉牙的命令了,需要使用信号控制: master进程可以理解以下信号 INT, TERM 立刻终止 QUIT 平滑终止 USR1 重新打开日志文件 USR2 平滑重载所有worker进程并重新载入配置和二进制模块
- 参考:https://www.cnblogs.com/cocol...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。