深刻理解PHP-FPM

FPM是什么


FPM(FastCGI Process Manager)是PHP FASTCGI运行模式的一个进程管理器。php

问题来了,既然是进程管理器,用来管理什么进程呢?
这就引出FastCGI协议web

什么是FastCGI协议?
FastCGI是web服务器(如Nginx、Apache)和处理程序之间的一种通讯协议。它是与HTTP相似的一种应用层通讯协议。注意:它只是一种协议。
在网络应用场景下,PHP并无像GOlang那样实现HTTP网络库,而是实现的FastCGI协议,而后与web服务器配合实现了HTTP的处理,web服务器来处理HTTP请求,而后将解析的结果再经过FastCGI协议转发给处理程序,处理程序处理完成后将结果返回给web服务器,web服务器再返回给用户。安全

扩展之-经常使用的网络处理模型服务器

  • 多进程模型:由一个主进程和多个子进程组成,主进程负责管理子进程,基本的网络事件由多个子进程处理,Nginx采用的就是这种模型。
  • 多线程模型:与多进程类型,只是它是线程粒度,这种模型一般会由主进程监听、接收请求,而后交由子线程处理,memcached就是这种模式;有的也是采用多进程那种模式-主线程只负责管理子线程不处理网络事件,各个子线程监听、接收、处理请求,memcached使用UDP协议时采用的是这种模式。

进程拥有独立的地址空间及资源,而线程没有,线程之间共享进程的地址空间及资源,因此在资源管理上多进程模型比较简单,而多线程模型则须要考虑不一样线程之间资源冲突,也就是线程安全。网络

基本实现


FPM是一个多进程模型,它由一个master进程和多个worker进程组成。master进程启动时会建立一个socket,可是不会接收、处理请求,而是fork出多个worker子进程完请求的接收及处理。多线程

master进程的主要工做是管理worker进程,负责fork或者kill掉进程,好比当请求比较多处理不过来时,master进程会尝试fork新的worker进程进程处理,而当空闲worker进程比较多时则会杀掉部分子进程,避免占用、浪费系统资源。并发

worker进程的主要工做是处理请求,每一个worker进程会竞争的Accept请求,接受成功后解析FastCGI,而后执行相应的脚本,处理完成后关闭请求,继续等待新的链接,这就是一个worker进程的生命周期。从worker进程的生命周期能够看到:一个worker进程只能处理一个请求,只有将一个请求处理完成后才会处理下一个请求。这与Nginx的事件模型有很大的区别,Nginx的子进程经过epoll管理套接字,若是一个请求数据还未发送完成则会处理下一个请求,它是非阻塞的模型,只处理活跃的套接字。FPM的这种处理模式大大简化了PHP的资源管理,使得在FPM模式下不须要考虑并发致使的资源冲突。socket

master进程与worker进程之间不会直接进行通讯,master通讯共享内存获取worker进程的信息,好比worker进程当前状态、已处理请求数等,master进程经过发送信号的方式杀掉worker进程。tcp

FPM能够同时监听多个端口,每一个端口对应一个worker pool,每一个pool下对应多个worker进程,相似Nginx中server的概念,这些归属不一样pool的worker进程扔由一个master管理。worker pool的结构为fpm_worker_pool_s,pool之间构成一个链表
在php-fpm.conf中经过[pool name]声明一个worker pool,每一个pool各自配置监听的地址、进程管理方式、worker进程数等。memcached

[pool name1]
listen = 127.0.0.1:9000
...
[pool name2]
listen = 127.0.0.1:9001
...
;isten = /dev/shm/php-fpm0.socket //可使用tcp或者unix socket的方式,可是必须区别于其余池的配置,好比tcp的端口不能同样,socket的文件不能同样
pm=dynamic   //进程模型: static、dynamic、ondemand
pm.max_children=50 //最大worker进程数
pm.start_servers=5 //启动时初始化的worker数
pm.min_spare_servers=5 //最小空闲worker数
pm.max_spare_servers=35  //最大空闲worker数
pm.process_idle_timeout=10  //worker空闲时间
pm.pm_max_requests //worker处理的最多请求数,超过这个值worker将被kill

扩展之PHP-FPM的多个进程池

每一个池使用不一样的配置,各个池之间互不干涉。默认状况下,PHP 只启用了一个池,全部请求均在这个池中执行。一旦某些请求出现拥堵之类的状况,那么极可能会连累整个池出现问题;若是启用多个池,那么能够把请求分门别类放到不一样的池中执行,此时若是某些请求出现拥堵之类的状况,那么只会影响本身所在的池,从而控制故障的波及范围。

设置多个进程池,每一个进程池分配不一样的站点,能够作到一个站占用资源过多致使其它站也不能访问的尴尬状况。这使得网站能够更好的运行,若是某个站点受到少许CC攻击,也不至于拖跨全部的站点。

参考书籍:《PHP7内核剖析》

相关文章
相关标签/搜索