PHP-FPM是一种多进程模型,由master和worker组成
MASTER进程
当master进程启动时,会创建一个socket,但是他本身并不接收/处理请求。他会fork出子进程来完成请求的接收和处理。所以,master的主要职责是管理worker进程,比如fork出worker进程,或者kill掉worker进程。
master进程并不直接与worker进程进行通信,那么他是如何管理worker进程呢?实际上,master进程通过共享内存的方式来读取worker进程的状态信息,包括:worker进程当前状态,worker进程已经处理的请求数量等等。master进程会通过发送信号的方式来kill掉worker进程。
WORKER进程
Fpm中的worker进程的主要工作是处理请求。每个worker进程会竞争Accept请求,接收成功的那一个来处理本次请求。请求处理完毕后又重新进入等待状态。此处需要注意的是:一个worker进程在同一时刻只能处理一个请求。这与Nginx的事件驱动模型有很大的区别。Nginx的子进程使用epoll来管理socket,当一个请求的数据还未发送完成的话他就会处理下一个请求,即同一时刻,一个子进程会连接多个请求。而Fpm的这种子进程处理方式则大大简化了PHP的资源管理,使得在Fpm模式下我们不需要考虑并发导致的资源冲突。
- PHP-FPM和PHP的生命周期
PHP单进程的生命周期
1、模块初始化阶段(Module init) MINIT:
即调用每个扩展源码中的的PHP_MINIT_FUNCTION中的方法初始化模块,进行一些模块所需变量的申请,内存分配等。
2、请求初始化阶段(Request init) RINIT:
即接受到客户端的请求后调用每个扩展的PHP_RINIT_FUNCTION中的方法,初始化PHP脚本的执行环境。
3、执行PHP脚本
4、请求结束(Request Shutdown) RSHUTDOWN:
这时候调用每个扩展的PHP_RSHUTDOWN_FUNCTION方法清理请求现场,并且ZE开始回收变量和内存。
5、关闭模块(Module shutdown) MSHUTDOWN:
Web服务器退出或者命令行脚本执行完毕退出会调用扩展源码中的PHP_MSHUTDOWN_FUNCTION 方法
PHP-FPM下的PHP生命周期
3. PHP-FPM配置
STATIC(静态)模式和dynamic(动态)模式的区别
默认为dynamic模式,在此模式下fpm会根据实际,动态的生成worker进程。FPM会有一个1s的定时器,不停的扫描空闲worker进程的数量,数量不足时,fork新的worker进程;空闲太多时,会自动kill相关worker进程。此方法能够节约内存,但是不适合秒杀这种大规模的并发,因为生成进程需要占用资源,突然大规模的并发,系统来不及生成work,会导致错误。
static模式下,系统根据配置直接生成相应数量的worker进程。适用于需要固定worker数量的场景,比如大规模的秒杀。但是问题也是显而易见的,在低流量的情况下,static无法动态控制worker的进程数,导致资源的浪费。
STATIC(静态)模式的配置
vim /etc/php/7.2/fpm/pool.d/www.conf
// 设置为静态模式
pm = static
// 初始化worker进程数量
pm.max_children = 500
// 这是为了防止出现不可预知的内存泄露,当我们把 pm 设成 static 时一般都会同时配置一下 pm.max_requests,这个配置代表当一个 PHP-FPM 进程处理了 1000 个请求之后就会主动退出进程,然后再由 FPM 管理进程启动一个新的 PHP-FPM 进程,这样即使有内存泄露发生,这种类似于重启的操作也会将泄露的内存释放掉
pm.max_requests = 1000
// 重启服务
service php7.2-fpm restart
// 查看目前的进程数
ps aux|grep php-fpm|wc -l
dynamic(静态)模式的配置
pm.max_children = 50 //是最大可创建的子进程的数量。必须设置。这里表示最多只能50个子进程。
pm.start_servers = 20 //随着php-fpm一起启动时创建的子进程数目。默认值:min_spare_servers + (max_spare_servers - min_spare_servers) / 2。这里表示,一起启动会有20个子进程。
pm.min_spare_servers = 10
//设置服务器空闲时最小php-fpm进程数量。必须
// 保证空闲进程数最小值,如果空闲进程小于此值,则创建新的子进程
pm.max_spare_servers = 3
// 保证空闲进程数最大值,如果空闲进程大于此值,则进行清理
还有一种ondemand模式,用的少