FPM(FastCGI 进程管理器)
用于替换 PHP FastCGI
的大部分附加功能,对于高负载网站是非常有用的。比方说: 支持平滑停止/启动的高级进程管理功能、文件上传优化支持、stdout
和 stderr
日志记录等等,更多请移步官网 https://www.php.net/manual/zh/install.fpm.php
从CGI到PHP-FPM
这个东西还得从 cgi
说起,慢慢的我们使用起来了 php-fpm
。
- CGI
common gateway interface (公共网关接口)
,每当客户请求CGI
的时候,WEB
服务器就请求操作系统生成一个新的CGI
解释器进程(如php-cgi.exe
),CGI
的一个进程则处理完一个请求后退出,下一个请求来时再创建新进程。当然,这样在访问量很少没有并发的情况也行。可是当访问量增大,并发存在,这种方式就不适合了。于是就有了fastcgi
- FastCGI
像是一个常驻型的CGI
,它可以一直执行着,只要激活后,不会每次都要花费时间去fork
一次(这是CGI
最为人诟病的fork-and-execute
模式)
在启动FastCGI
的时候它就启动了多个 CGI
解释器进程并等待Web Server
来连接,结束完就又重新接客
,在CGI
模式中,php-cgi
在此便退出了。
- PHP-FPM
它就是FastCGI
的实现,并提供了进程管理的功能,进程包含 master
进程和 worker
进程两种进程。master
进程只有一个,负责监听端口,接收来自 Web Server
的请求,而 worker
进程则一般有多个(具体数量根据实际需要配置),
每个进程内部都嵌入了一个 PHP
解释器,是 PHP
代码真正执行的地方。
多方面调优
php.ini 配置
- 配置文件
/etc/php/7.2/fpm/php.ini
;这个是配置禁用危险函数
disable_functions=eval...
;上传文件大小限制
post_max_size =16M
upload_max_filesize= 16M
;脚本执行时间限制
max_execution_time= 60
max_input_time =60
;脚本内存限制,一般设为128M,如非必要(无可避免的上传大文件/处理大数组)不增加
memory_limit =128M
php-fpm 配置
- 配置文件
/etc/php/7.2/fpm/php-fpm.conf
;错误日志处理
error_log =/var/log/php-fpm/error.log
log_level = notice
;异常自启(表示60s内出现 60次 SIGSEGV orSIGBUS 异常时候,自动重启)
emergency_restart_threshold= 60
emergency_restart_interval= 60s
;设置子进程接受主进程复用信号的超时时间
process_control_timeout= 0
;后台执行php-fpm
daemonize = yes
pool 资源池配置
- 配置文件
/etc/php/7.2/fpm/pool.d/*.conf
(每个文件代表一个资源池,机器性能足够时候,可以区分多个资源池,隔绝不同的php应用),默认是 www.conf
既然是进程管理器,当然这个进程是很重要的,这里我也不禁回想起我刚刚搞PHP
的时候,当时不了解这个PHP-FPM
,老是前端请求接口,一下子就挂了,后看日志才发现,是进程就没设置过,所以这里需要说明一下,这个进程怎么设置才是合理的
;监听方式,用tcp方式较稳定
listen = 127.0.0.1:9000
;backlog,排队长度设置
listen.backlog = 4096
;慢处理日志,表示超过45秒则记录为慢处理
request_slowlog_timeout = 45s
slowlog = /var/log/php-fpm/www-slow.log
重点 进程设置问题
在设置资源池的时候,有很多pm
的配置
- pm
pm
默认是dynamic
动态的,但是一般我们的生产环境都是静态的,pm=static
- pm.max_children
最大子进程数量,越多越好,但是需要根据我们的服务器来设置,一般每个php-cgi
所耗费的内存为20M ~ 30M,如果最大数量设置为100,则在峰值的时候php-cgi
所耗内存在2000M ~ 3000M
,如果这个值设置的比较小,那么等待的请求时间会出现502超时,可以根据你们服务器运行的程序,计算出剩余内存,再计算子进程数
- pm.max_requests
为避免内存泄露,php-fpm
有这么一个机制,当一个php-cgi
进程处理的请求数达到这个配置后,则会自动重启该进程,所以在高并发中,经常导致502错误,解决方法就是把这个值设置大一些,减少进程重启次数,减少高并发情况下502错误。我一般设置为1024
- pm.min_spare_servers
保证空闲进程数最小值,如果空闲进程小于此值,则创建新的子进程,一般可以设置为10
- pm.max_spare_servers
保证空闲进程数最大值,如果空闲进程大于此值,此进行清理,一般可以设置为30
- request_terminate_timeout
单个请求的超时中止时间,超时后会终止进程,nginx
发现信号断了,就会给客户端返回502错误。
和php.ini的max_execution_time配置不冲突,谁先达到时间谁先起作用。由于程序中有请求第三方接口等待,所以建议这个值设置为400秒,长一点不会出现502错误
希望大家看完后可以选择合适的配置来用于项目的生产环境。