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 是什么 公共网关接口 ...
随机推荐
- exec函数族,守护进程,线程同步和互斥
2015.3.2 进程和程序有三点不同:1,存在位置不同,程序:硬盘,磁盘.进程:内存2. 程序是静态的,进程是动态的 执行./a.out -->bash->bash程序调用fork()- ...
- gcc学习笔记
1:第一个程序 : hello world #include <stdio.h> int main(void) { printf("Hello , world ! \n" ...
- join()、implode()函数
join() 函数 join() 函数把数组元素组合为一个字符串. join() 函数是 implode() 函数的别名. 语法 join(separator,array) 参数 描述 separat ...
- Magento文件系统目录结构
magento │ .htaccess│ cron.php //系统cron程序,修改 linux的cron运行,加入magento的一些定时处理│ cron.sh│ favicon.ico ...
- Python 基礎 - if else流程判斷
hmm~前面講了那麼多,終於可以稍稍的正式進入另一個階段,沒錯,要開始寫判斷式了 這次先從最簡單的判斷式開始,if else 開始- Go 首先,之前有寫有一個簡單的互動式 用戶輸入 的代碼,忘記了嗎 ...
- python数据结构与算法——二叉树结构与遍历方法
先序遍历,中序遍历,后序遍历 ,区别在于三条核心语句的位置 层序遍历 采用队列的遍历操作第一次访问根,在访问根的左孩子,接着访问根的有孩子,然后下一层 自左向右一一访问同层的结点 # 先序遍历 # ...
- Flume 实战(1) -- 初体验
前言: Flume-ng是数据收集/聚合/传输的组件, Flume-ng抛弃了Flume OG原本繁重的zookeeper和Master, Collector, 其整体的架构更加的简洁和明了. 其基础 ...
- JAVA中精确计算金额BigDecimal
package com.chauvet.utils; import java.math.BigDecimal; import java.text.DecimalFormat; import java. ...
- thrift demo
基于上一篇博客,安装thrift complier之后,就需要进行跑跑程序,来看看是否如同预期的那种效果. 前面的thrift compiler的主要作用,其实就是为了IDL的,就是防止客户端和服务端 ...
- PHP 输出图像 imagegif 、imagejpeg 与 imagepng 函数
imagegif().imagejpeg().imagepng() 和 imagewbmp() 函数分别允许以 GIF.JPEG.PNG 和 WBMP 格式将图像输出到浏览器或文件. PHP 输出图像 ...