PHP-FPM多方面调优策略

FPM(FastCGI 进程管理器)用于替换 PHP FastCGI 的大部分附加功能,对于高负载网站是非常有用的。比方说: 支持平滑停止/启动的高级进程管理功能、文件上传优化支持、stdoutstderr 日志记录等等,更多请移步官网 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错误

希望大家看完后可以选择合适的配置来用于项目的生产环境。

您的支持是对我最大的鼓励!

发表于: 作者:憧憬。
关注互联网以及分享全栈工作经验的原创个人博客和技术博客,热爱编程,极客精神
Github 新浪微博 SegmentFault 掘金专栏