CGI、FastCGI 和 PHP-FPM 关系图解

CGI、FastCGI 和 PHP-FPM 关系图解

在搭建 LAMP/LNMP 服务器时,会经常遇到 PHP-FPM、FastCGI和CGI 这几个概念。如果对它们一知半解,很难搭建出高性能的服务器。接下来我们就以图形方式,解释这些概念之间的关系。

本文章系转载整理。由于整理之后忘记了原文链接。如果大家知道请联系我。我加上来。

1 基础

在整个网站架构中,Web Server(如 Apache)只是内容的分发者。举个例子,如果客户端请求的是 index.html,那么 Web Server 会去文件系统中找到这个文件,发送给浏览器,这里分发的是静态数据。

cgi-0x01.png

如果请求的是 index.php,根据配置文件,Web Server 知道这个不是静态文件,需要去找 PHP 解析器来处理,那么他会把这个请求简单处理,然后交给 PHP 解析器。

cgi-0x02.png

当 Web Server 收到 index.php 这个请求后,会启动对应的 CGI 程序,这里就是 PHP 的解析器。接下来 PHP 解析器会解析 php.ini 文件,初始化执行环境,然后处理请求,再以规定 CGI 规定的格式返回处理后的结果,退出进程,Web server 再把结果返回给浏览器。这就是一个完整的动态 PHP Web 访问流程。接下来再引出这些概念,就好理解多了,

  • CGI:是 Web Server 与 Web Application 之间数据交换的一种协议。
  • FastCGI:同 CGI,是一种通信协议,但比 CGI 在效率上做了一些优化。同样,SCGI 协议与 FastCGI 类似。
  • PHP-CGI:是 PHP (Web Application)对 Web Server 提供的 CGI 协议的接口程序。
  • PHP-FPM:是 PHP(Web Application)对 Web Server 提供的 FastCGI 协议的接口程序,额外还提供了相对智能一些任务管理。

WEB 中:

  • Web Server 一般指 Apache、Nginx、IIS、Lighttpd、Tomcat 等服务器。
  • Web Application 一般指 PHP、Java、Asp.net 等应用程序。

2 Module方式

在了解 CGI 之前,我们先了解一下Web server 传递数据的另外一种方法:PHP Module加载方式。以 Apache 为例,在PHP Module方式中,是不是在 Apache 的配置文件 httpd.conf 中加上这样几句:

# 加入以下2句
LoadModule php5_module D:/php/php5apache2_2.dll
AddType application/x-httpd-php .php

# 修改如下内容
<IfModule dir_module>
    DirectoryIndex index.php index.html
</IfModule>

上面是 Windows 下安装php和apache环境后手动配置,在linux下源码安装大致是这样配置的:

# ./configure --with-mysql=/usr/local --with-apache=/usr/local/apache --enable-track-vars

所以,这种方式,他们的共同本质都是用 LoadModule 来加载 php5_module,就是把php作为apache的一个子模块来运行。当通过 web 访问 php 文件时,apache 就会调用 php5_module 来解析 php 代码。

那么 php5_module 是怎么来将数据传给php解析器来解析 PHP 代码的呢?答案是通过 sapi。

我们再来看一张图,详细的说说 apache 与 php 与 sapi 的关系:

cgi-0x03.png

从上面图中,我们看出了 sapi 就是这样的一个中间过程,SAPI 提供了一个和外部通信的接口,有点类似于socket,使得 PHP 可以和其他应用进行交互数据(Apache,Nginx 等)。PHP 默认提供了很多种 SAPI,常见的提供给 Apache 和 nginx 的 php5_module、CGI、FastCGI,给 IIS 的 ISAPI,以及 Shell 的 CLI。

所以,以上的 apache 调用 PHP 执行的过程如下:

apache -> httpd -> php5_module -> sapi -> php

好了。Apache 与 PHP 通过 php5_module 的方式就搞清楚了吧!

这种模式将 PHP 模块安装到 Apache 中,所以每一次 Apache 结束请求,都会产生一条进程,这个进程就完整的包括 PHP 的各种运算计算等操作。

在上图中,我们很清晰的可以看到,Apache 每接收一个请求,都会产生一个进程来连接 PHP 通过 sapi 来完成请求,可想而知,如果一旦用户过多,并发数过多,服务器就会承受不住了。而且,把 mod_php 编进 Apache 时,出问题时很难定位是 PHP 的问题还是 Apache 的问题。

3 CGI

CGI(Common Gateway Interface)全称是“通用网关接口”,WEB 服务器与PHP应用进行“交谈”的一种工具,其程序须运行在网络服务器上。CGI 可以用任何一种语言编写,只要这种语言具有标准输入、输出和环境变量。如PHP、Perl、tcl 等。

WEB 服务器会传哪些数据给 PHP 解析器呢?URL、查询字符串、POST 数据、HTTP header 都会有。所以,CGI就是规定要传哪些数据,以什么样的格式传递给后方处理这个请求的协议。仔细想想,你在 PHP 代码中使用的用户从哪里来的。

也就是说,CGI 就是专门用来和 web 服务器打交道的。WEB 服务器收到用户请求,就会把请求提交给 CGI 程序(如 PHP-CGI),CGI 程序根据请求提交的参数作应处理(解析 PHP),然后输出标准的 html 语句,返回给 WEB 服服务器,WEB 服务器再返回给客户端,这就是普通 CGI 的工作原理。

CGI 的好处就是完全独立于任何服务器,仅仅是做为中间分子。提供接口给 Apache 和 PHP。他们通过 CGI 搭线来完成数据传递。这样做的好处了尽量减少两者之间的关联,使他们两者之间变得更独立。

但是 CGI 有个蛋疼的地方,就是每一次 WEB 请求都会有启动和退出过程,也就是最为人诟病的 fork-and-execute 模式,这样一在大规模并发下,就死翘翘了。

4 FastCGI 简单介绍

从根本上来说,FastCGI 是用来提高 CGI 程序性能的。类似于 CGI,FastCGI 也可以说是一种协议

FastCGI 像是一个常驻(long-live)型的 CGI,它可以一直执行着,只要激活后,不会每次都要花费时间去 fork 一次。它还支持分布式的运算, 即 FastCGI 程序可以在网站服务器以外的主机上执行,并且接受来自其它网站服务器来的请求。

FastCGI 是语言无关的、可伸缩架构的 CGI 开放扩展,其主要行为是将 CGI 解释器进程保持在内存中,并因此获得较高的性能。众所周知,CGI 解释器的反复加载是 CGI 性能低下的主要原因。如果 CGI 解释器保持在内存中,并接受 FastCGI 进程管理器调度,则可以提供良好的性能、伸缩性、Fail - Over 特性等等。

5 FastCGI的工作原理

FastCGI 接口方式采用 C/S 结构,可以将 HTTP 服务器和脚本解析服务器分开,同时在脚本解析服务器上启动一个或者多个脚本解析守护进程。当 HTTP 服务器每次遇到动态程序时,可以将其直接交付给 FastCGI 进程来执行,然后将得到的结果返回给浏览器。这种方式可以让 HTTP 服务器专一地处理静态请求,或者将动态脚本服务器的结果返回给客户端,这在很大程度上提高了整个应用系统的性能。

cgi-0x04.png
  1. Web Server 启动时载入 FastCGI 进程管理器(Apache Module 或 IIS ISAPI 等)
  2. FastCGI 进程管理器自身初始化,启动多个 CGI 解释器进程(可建多个 PHP-CGI),并等待来自Web Server的连接。
  3. 当客户端请求到达 Web Server 时,FastCGI 进程管理器选择并连接到一个 CGI 解释器。Web server 将 CGI 环境变量和标准输入发送到 FastCGI 子进程 PHP-CGI。
  4. FastCGI 子进程完成处理后,将标准输出和错误信息从同一连接返回 Web Server。当 FastCGI 子进程关闭连接时,请求便告处理完成。FastCGI 子进程接着等待,并处理来自 FastCGI 进程管理器(运行在 Web Server 中)的下一个连接。 在 CGI 模式中,PHP-CGI 在此便退出了。

FastCGI 与 CGI 特点:

  1. 对于 CGI 来说,每一个 Web 请求 PHP 都必须重新解析 php.ini、重新载入全部扩展,并重新初始化全部数据结构。而使用 FastCGI,所有这些都只在进程启动时发生一次。一个额外的好处是,持续数据库连接(Persistent database connection)可以工作。
  2. 由于 FastCGI 是多进程,所以比 CGI 多线程消耗更多的服务器内存,PHP-CGI 解释器每进程消耗 7~25 M内存,将这个数字乘以 50 或 100 就是很大的内存数。

6 PHP-FPM介绍

要了解 PHP-FPM,就得先说说 PHP-CGI。

PHP-CGI 就是 PHP 实现的自带的 FastCGI 管理器。 虽然是 PHP 官方出品,但是这丫的却一点也不给力,性能太差,而且也很麻烦不人性化,主要体现在:

  1. PHP-CGI 变更 php.ini 配置后,需重启 PHP-CGI 才能让新的 php-ini 生效,不可以平滑重启。
  2. 直接杀死 PHP-CGI 进程,php就不能运行了。

上面两个问题,一直让很多人病垢了很久。所以很多人一直还是在用 Module 方式。 直到 2004 年一个叫 Andrei Nigmatulin 的屌丝发明了 PHP-FPM ,这神器的出现就彻底打破了这种局面,这是一个 PHP 专用的 FastCGI 管理器,它很爽的克服了上面两个问题,而且,还表现在其他方面更表现强劲。

也就是说,PHP-FPM 是对于 FastCGI 协议的具体实现,他负责管理一个进程池,来处理来自 Web 服务器的请求。目前,PHP5.3 版本之后,PHP-FPM 是内置于 PHP 的

因为 PHP-CGI 只是个 CGI 程序,他自己本身只能解析请求,返回结果,不会进程管理。所以就出现了一些能够调度 PHP-CGI 进程的程序,比如说由 lighthttpd 分离出来的 spawn-fcgi。同样,PHP-FPM 也是用于调度管理 PHP解析器 PHP-CGI 的管理程序。

PHP-FPM 通过生成新的子进程可以实现 php.ini 修改后的平滑重启。

7 总结

最后,我们来总结一下,这些技术经过不断的升级,可以解决什么问题(不然也不会升级嘛)。

cgi-0x05.png

所以,如果要搭建一个高性能的 PHP WEB 服务器,目前最佳的方式是 Apache/Nginx + FastCGI + PHP-FPM(+PHP-CGI) 方式了,不要再使用 Module 加载或者 CGI 方式啦:)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容