相信写过PHP程序的朋友对PHP-FPM应该不陌生,它是我们PHP程序中非常重要的一环,当一个网络请求进来时,会先经过Nginx,随后就会转发给PHP-FPM执行实际的业务逻辑。
一个完整的PHP网络请求如下:

简单来说就是一个请求首先会经过Nginx服务器(看每个人的实际架构),Nginx会根据配置的fastcgi_pass 地址找到我们的fastcgi服务器,即PHP-FPM监听的地址,进而将网络请求传递给PHP-FPM,PHP-FPM收到请求后,会启动一个worker进程进行处理,并将最终的结果返回给Nginx。
那么**什么是FastCgi服务器,它与PHP-FPM又是什么关系?**其实上面我已经透露了,不过我们还是先从CGI说起。
CGI,全称Common Gateway Interface,即通用网关接口。CGI是一种协议,它的目的是让我们的交互程序(代码)与Web服务器(如Nginx)进行通信。通过定义协议,可以规定Web服务器需要传递哪些数据,以及数据的格式是怎样的,这样只要实现了CGI规范的程序,都可以处理Web服务器传递过来的请求。
那什么是FastCGI呢?其实FastCGI就是CGI的改进版,目的就是要让CGI程序处理地更快。这是因为CGI的工作方式是fork-and-execute的模式,即每次遇到一个请求,都会启动一个新的CGI进程处理,处理完毕之后再关闭。当请求量比较大时,启动的进程数也会非常多,不断占用操作系统的CPU、内存等。
FastCGI是如何改进的呢?与CGI为每一个请求创建一个新的进程不同,FastCGI使用常驻的进程来处理一系列的请求,这些进程由FastCGI管理器管理,而不是Web服务器。FastCGI的工作模式是一种C/S架构,FastCGI管理器即我们常见的Master进程,而FastCGI进程即我们常见的Worker进程。
当网络请求达到Web服务器时,FastCGI管理器会选择并连接到一个FastCGI进程,同时还会将请求信息以及环境变量传递给其进行处理,CGI处理完毕并关闭连接后,本次请求也就到此结束。但此时FastCGI进程并不会销毁退出,而是继续等待新的连接进行处理。
从上面可以看到:每个单独的FastCGI进程在其生命周期内可以处理许多请求,从而避免了每个请求进程创建和终止的开销,进而提高处理的效率与速度。
那什么是PHP-FPM呢?我们知道FastCGI和CGI只是一种规范,而PHP-FPM就是一个实现了FastCGI规范的程序,只不过它是PHP的。
PHP-FPM启动的时候会有一个Master进程和多个Worker进程,Master进程就是我们前面说的FastCGI管理器,而Worker进程就是前面说的FastCGI进程。
$ ps -ef | grep php-fpm
root 8773 1 0 May29 ? 00:01:46 php-fpm: master process (/xxx/php/etc/php-fpm.conf)
www 8774 8773 0 May29 ? 00:00:13 php-fpm: pool php_service
www 8775 8773 0 May29 ? 00:00:13 php-fpm: pool php_service
www 8776 8773 0 May29 ? 00:00:13 php-fpm: pool php_service
www 8777 8773 0 May29 ? 00:00:13 php-fpm: pool php_service
www 8778 8773 0 May29 ? 00:00:13 php-fpm: pool php_service
www 8779 8773 0 May29 ? 00:00:13 php-fpm: pool php_service
...
至此,三者的关系总结如下:
CGI和FastCGI都是一种规范,目的是使我们的交互程序与Web服务器进行通信,不过FastCGI是CGI的改进版,目的是解决CGI处理效率低下的问题,而PHP-FPM则是FastCGI的具体实现,用于PHP程序。