CGI、FastCGI和PHP-FPM浅析
这段时间对Nginx+PHP-FPM的概念和机制一直不太清晰,趁着同事的分享和看过的几篇博文和资料,重新将思路处理一下。
首先,PHP-FPM(FastCGI Process Manager: FastCGI进程管理器)是一种针对PHP的FastCGI,针对PHP语言的一种进程管理器。FastCGI顾名思义就是一种快速的CGI(Common Gateway Interface)。因此为了能够理解PHP-FPM,我们首先应该了解CGI是怎么样一个机制。
1 CGI(Common Gateway Interface)
CGI(通用网关接口)是架起服务器Web Server和处理来自客户端请求的程序之间沟通的桥梁,也就是说是一个第三方的协议规定。当服务器接收到用户端的请求是静态请求时,Web Server会去对应的文件系统中找到这个文件,然后发送给浏览器。但是如果用户的请求是一种动态的请求,Web Server (如Nginx)就不知道如何处理这个请求了,既然自己不知道如何处理,就要求助或者说是承包给第三方。但是交给第三方处理这个请求的时候,总得告诉第三方一些请求的参数吧,这就像软件领域的需求的对接一样,规定我给你什么输入,然后你给我什么输出结果,CGI就是这种约定,规定了输入的参数和输出的结果的一种协议。在处理动态请求的情况下,其流程图如下:

图1 CGI对请求处理流程图
用文字描述如下:
1.用户通过Http将动态请求发送到Web Server;
2.Web Server通过使用unix domain socket,或者ip socket将请求转发给CGI(如果使用ip socket的话,允许将Web Server 和CGI部署在不同的机器上);
3.CGI fork一个对应的进程处理来自客户端的动态请求,得到执行的结果;
4.执行的结果经过同一个socket连接通过CGI返回给Web server;
5.有Web Server将数据发送个客户端;
也就是说在这个过程中Web Server只是负责执行静态页面的请求以及接受用户的动态请求并转发给相应的处理程序,然后将动态请求处理程序的输出结果返回给客户端。这可以减轻Web Server的工作负担,使得Web Serve能够在更高并发的请求环境中工作。
2 FastCGI的工作方式
CGI虽然提供了Web Server和请求处理程序之间的一种接口规范,但是却饱受诟病。如下图所示,其原因在于CGI是以一种按需派生的方式工作的,也就是说在接收到Web Server转发的请求之后,就需要重新fork一个进程处理来自客户端的请求,但是fork一个进程的代价一般比较昂贵。在并发性不是很高的情况下,这种工作方式也许能工作的很好,但是如果并发性很高就会导致频繁的fork进程并处理请求,给运行CGI的机器造成很大的压力。其实仔细分析fork进程(如图3所示)所发生的事情可以清晰地看到有一些步骤是重复进行的,因此这些步骤是可以省略掉的,因此就诞生了FastCGI。FastCGI是在CGI的架构思想的扩展,其核心思想在于在Web Server和CGI之间建立起一个智能的可持续的中间层用于统筹CGI程序的管理,因此FastCGI可以被看做是一个CGI的进程管理器。其工作流程图如下:

图2 FastCGI对请求的处理流程图
其中的Fastcig-wrapper可以理解为用于启动另一个程序的程序。FastCGI的工作流程如下所述:
1.FastCGI进程管理器执行自身的初始化,启动多个worker进程并等待来自Web Server的连接,其中启动FastCGI进程的时候可以配置以ip socket和unix domain socket两种方式启动;
2.当客户端请求到达Web Server的时候,Web Server将请求采用ip socket或者unix domain socket发送到FastCGI的主进程(也叫master进程),master进程选择连接到一个worker进程。Web服务器将CGI的环境变量和标准输入发送到worker进程;
3.worker进程处理完成之后将输出通过同一个Socekt连接发送会Web Server。当worker进程处理完请求之后,关闭socket连接。如果没有达到为该进程设置的处理的请求数上限,则继续存在而不会消亡,等待下次的处理请求。
3 CGI和FastCGI的不同之处
为了清晰地说明CGI和FastCGI之间的不同,图3说明了FastCGI和CGI之间的执行步骤的不同之处。图中Individual Request代表着FastCGI的请求处理流程图,而PHP Lifespan很明显就代表着CGI处理请求的流程图。从图中可以看出相对于CGI而言FastCGI处理外部的动态请求时不用为每个请求执行PHP的MINIT(即PHP的模块初始化过程,需要加载php.ini,为php启动的第一个步骤)过程。之所以会出现这种情况,究其原因在于worker进程启动的时候这个步骤已经完成了,worker进程是常驻内存的且不止可以处理一次请求,因此只需要针对特定的请求初始化(RINIT)就可以了,也就是说不用对每次请求都加载一次php.ini。在处理完本次请求之后,如果没有到达处理请求的上限该进程也不用消亡,也就没有了后面的扩展关闭步骤。但是CGI的执行模式是为每个请求fork一个子进程,每个子进程都是重新加载配置文件,按照php执行的步骤按部就班的执行,这也就造成了直接使用CGI的代价昂贵,尤其是在高并发的情况下。

图2 CGI和FastCGI声明周期示意图
4. PHP FastCGI---PHP-FPM的架构实现
PHP-FPM的进程管理方式为:存在的master进程可以管理多个pool,每个pool由master进程监听不同的端口,每个pool中又可以存在许多不同的worker进程。每个worker进程都常驻内存,并且随着请求数量的增多可以动态的增加,就是所谓的prefork动态增加;且每个worker进程都在达到最大的处理请求之后会自动重启,如果进程没有达到最大的请求数量而意外挂掉,则master会重启该worker进程。
虽然,worker进程的数量可以随着请求数量的增加prefork动态增加,但是由于资源的有限,worker进程的数量存在一个上限---pm.max_children,达到这个上限之后,如果还有额外的请求且worker进程都处于繁忙状态,那么该请求会被master进程挂起到连接队列backlog中(默认值为511)。
在项目中Nginx和PHP-FPM是一种很好的解耦方式,Nginx的优势之处在于处理高并发,所有的静态界面的处理都由Nginx处理;而PHP-FPM专注于处理php请求,每个请求对应一个php的页面,这样实现了动态界面和静态界面处理的分离,减轻了Nignx的负担。
5. 总结
这篇文章对CGI和FastCGI的工作方式简单的介绍,并对二者的工作方式做了简要的对比,FastCGI由于worker进程常驻内存,能够很大程度上提高并发性。最后对采用FastCGI的PHP-FPM做了简要的介绍。
CGI、FastCGI和PHP-FPM浅析的更多相关文章
- Nginx + CGI/FastCGI + C/Cpp
接着上篇<Nginx安装与使用>,本篇介绍CGI/FASTCGI的原理.及如何使用C/C++编写简单的CGI/FastCGI,最后将CGI/FASTCGI部署到nginx.内容大纲如下: ...
- 漫谈CGI FastCGI WSGI
作者:auxten链接:https://zhuanlan.zhihu.com/p/20054757来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. CGI(Common ...
- [转] Nginx + CGI/FastCGI + C/Cpp
接着上篇<Nginx安装与使用>,本篇介绍CGI/FASTCGI的原理.及如何使用C/C++编写简单的CGI/FastCGI,最后将CGI/FASTCGI部署到nginx.内容大纲如下: ...
- PHP运行模式(cgi,fast-cgi,cli, ISAPI ,web模块模式)【转载】
PHP运行模式有5钟: 1)cgi 通用网关接口(Common Gateway Interface))2)fast-cgi 常驻 (long-live) 型的 CGI3)cli 命令行运行 (C ...
- cgi fast-cgi php-fpm区别
php-cli 是php在系统执行的程序,直接执行php文件: cgi和fast-cgi的区别1.cgi和fast-cgi都是php解析协议,负责解析服务器分发过来的php动态文件:cgi程序就会去解 ...
- 转:nginx+CGI/FASTCGI
简介版: 1.fastcgi与cgi区别:fastcgi通过线程来响应请求,而cgi对每个请求生成一个进程. 2.典型nginx数据传输过程:user->nginx->本地socket(请 ...
- cgi fastcgi php-cgi php-fpm
参考: 摘至:http://www.cnblogs.com/thinksasa/p/4497567.html 详说fastcgi,php-fpm的区别:http://segmentfault.co ...
- 【转】Nginx + CGI/FastCGI + C/Cpp
接着上篇<Nginx安装与使用>,本篇介绍CGI/FASTCGI的原理.及如何使用C/C++编写简单的CGI/FastCGI,最后将CGI/FASTCGI部署到nginx.内容大纲如下: ...
- CGI fastCgi php-fpm PHP-CGI 辨析
CGI fastCgi php-fpm PHP-CGI 辨析 LNMP环境中的nginx是不支持php的,需要通过fastcgi插件来处理有关php的请求.而php需要php-fpm这个组件提供该功能 ...
- CGI & FastCGI 协议
目录 CGI 是什么 CGI 特点 CGI 的流程 FastCGI 是什么 CGI & FastCGI(转载) 推荐Blog: CGI是什么,FastCGI是什么 CGI 是什么 公共网关接口 ...
随机推荐
- javascript笔记8-表单脚本、JSON、AJAX
通过表单提交,很方便的可以从界面把参数传递给后台. 如果前后台我们有大量数据需要交互,JSON方便我们传递和读取. 如果需要更新一个界面的某一部分数据,并不想刷新界面,就要用到Ajax. 1. 表单脚 ...
- HDU 4822----其实不会这个题
题目:http://acm.hdu.edu.cn/showproblem.php?pid=4822 并不会做这个题,题解说是LCA(最近公共祖先),并不懂,说一下我自己的思路吧,虽然没能实现出来. 题 ...
- Ubuntu安装gfortran
命令行运行 sudo apt-get install gfortran
- PAT (Basic Level) Practise:1026. 程序运行时间
[题目链接] 要获得一个C语言程序的运行时间,常用的方法是调用头文件time.h,其中提供了clock()函数,可以捕捉从程序开始运行到clock()被调用时所耗费的时间.这个时间单位是clock t ...
- js数组常用方法汇总
判断某个对象是否是数组: instanceof.Array.isArray() 对于一个网页或者一个全局作用域可以使用instanceof操作符. if(value instanceof Array) ...
- linux下压缩与解压(zip、unzip、tar)详解
linux下压缩与解压(zip.unzip.tar)详解 2012-05-09 13:58:39| 分类: linux | 标签:linux zip unzip tar linux命令详解 |举报|字 ...
- C中变量名通过宏定义转换成char*类型字符串
#include <iostream> #include <stdlib.h> #define name_to_str(name)(#name) int main() { in ...
- kuangbin_MST C (POJ 2031)
全程double精度就能过了 间接0距离不用管 prim自动连起来的 G++交的话只能用%f输出 C++的话加不加l都可以 (这么说以后用%f肯定不会错咯) 不过我不懂为什么他们的空间时间差了好多倍. ...
- 装个centos虚拟机之设置桥接网络
问题1:设置静态ip 虚拟机网路选择桥接后,设置静态ip: (1):先看下当前用的哪个网络 (2):打开配置文件,修改内容 内容参照mac配置,(注意:mac网络配置里的路由器就是默认网关GATEWA ...
- DOM节点关系,节点关系
DOM节点关系 定义 节点中的各种关系可以用传统的家族关系来描述,相当于把文档树比喻成家谱. 属性 [nodeType.nodeName.nodeValue] 每个节点都有这三个属性,且节点类型不同, ...