CGI程序本身只能解析请求、回笼结果,不会历程经管,所以有一个致命的缺点,那即是每处分一个请求都需求fork一个全新的历程,跟着Web的鼓起,高并发越来越成为常态,这样低效的方式明显不可以满足需求(每一次web请求都会有启动和退出历程,也即是非常为人诟病的fork-and-execute模式,这样一在大规模并发下,就死翘翘了)。就这样,FastCGI降生了,CGI程序很快就退出了历史的舞台。
FastCGI (Fast CGI)
FastCGI,顾名思义即是更快的CGI程序,用来进步CGI程序性能,它允许在一个历程内处分多个请求,而不是一个请求处分完毕就直接结束历程,性能上有了很大的进步。
进步性能?辣么CGI程序的性能问题在哪呢?
PHP解析器会解析php.ini文件,初始化执行环境,即是这里了。尺度的CGI程序对每个请求都会执行这些步骤(不闲累啊!启动历程很累的说!),所以处分每个请求的时间会比较长。这明显分歧理嘛!首先,FastCGI会先启一个master历程,解析配置文件,初始化执行环境,而后再启动多个worker历程。当请求过来时,master会传递给一个worker,而后登时可以接受下一个请求。
这样就避免了重复的劳动,效率自然是高。并且当worker不够用时,master可以根据配置预先启动几个worker等着。当然空闲worker太多时,也会停掉少许,这样就进步了性能,也节约了资源。这即是FastCGI的对历程的经管。
PS:也有少许能够调剂PHP-CGI历程的程序,比如说由lighthttpd分离出来的spawn-fcgi。好了,PHP-FPM也是这么个东东,在长时间的发展后,渐渐得到了大家的认可(要晓得前几年大家可是诉苦PHP-FPM稳定性太差的),也越来越流行。
它是FastCGI协议的一个实现,任何实现了FastCGI协议的服务器都能够与之通讯。FPM之于尺度的FastCGI程序,也提供了少许增强功能。
FPM是一个PHP历程经管器,包含master和worker两种历程。
master历程只有一个,负责监听端口,接收来自服务器的请求,而worker历程则一般有多个(具体数量根据实际需求配置),每个历程里面都嵌入了一个PHP解释器,是PHP代码真正执行的地方,下面是我本机上FPM的历程环境:1个master历程,2个worker历程。
从FPM接收到请求,到处分完毕,其具体的流程如下:
FPM的master历程接收到请求。
master历程根据配置指派特定的worker历程进行请求处分,如果没有可用历程,回笼错误,这也是我们配合Nginx遇到502错误相对多的原因。
worker历程处分请求,如果超时,回笼504错误。
请求处分结束,回笼结果。
FPM从接收到处分请求的流程即是这样了,辣么Nginx又是怎样发送请求给FPM的呢?
我们晓得,Nginx不仅仅是一个Web服务器,也是一个功能强大的Proxy服务器,除了进行http请求的经销,也可以进行许多其他协议请求的经销,包含本文与FPM相关的FastCGI协议。为了能够使Nginx明白FastCGI协议,Nginx提供了FastCGI模块来将http请求映射为对应的FastCGI请求。
Nginx的FastCGI模块提供了fastcgi_param指令来主要处理这些映射关系,下面是Nginx的一个配置文件实例,其主要完成的工作是将Nginx中的变量翻译成PHP中能够理解的变量。
除此之外,非常重要的就是fastcgi_pass指令了,这个指令用于指定FPM进程监听的地址,Nginx会把所有的PHP请求翻译成FastCGI请求之后再发送到这个地址。下面一个简单的可以工作的Nginx配置文件:
在这个配置文件中,我们新建了一个虚拟主机,监听80端口,项目根目录为 /usr/local/web/myproject/public。然后我们通过location指令,将所有的以.php结尾的请求都交给FastCGI模块处理,从而把所有的PHP请求都交给了FPM处理,从而完成Nginx到FPM的闭环。如此以来,Nginx与FPM通信的整个流程应该比较清晰了。
修改了php.ini配置文件后,使用PHP-FPM为什么能平滑重启?
修改php.ini之后,PHP-CGI进程是没办法平滑重启的。PHP-FPM对此的处理机制是新的worker进程用新的配置,已经存在的worker进程处理完手上的活就可以歇着了,通过这种机制来平滑过渡。