关于CGI和FastCGI的理解

在搭建 LAMP/LNMP 服务器时,会常常遇到 PHP-FPM、FastCGI和CGI 这几个概念。若是对它们只知其一;不知其二,很难搭建出高性能的服务器。php

0.CGI的引入

在网站的总体架构中,Web Server(如nginx,apache)只是内容的分发者,对客户端的请求进行应答。html

若是客户端请求的是index.html这类静态页面,那么Web Server就去文件系统中找对应的文件,找到返回给客户端(通常是浏览器),在这里Web Server分发的就是是静态数据。linux

整个过程以下图:nginx

 

对于像index.php这类的动态页面请求,Web Server根据配置文件知道这个不是静态文件,则会调用PHP 解析器进行处理而后将返回的数据转发给客户端(浏览器)。c++

整个过程以下图:web

 

在这个过程当中,Web Server并不能直接处理静态或者动态请求,对于静态请求是直接查找而后返回数据或者报错信息,对于动态数据也是交付给其余的工具(这里的PHP解析器)进行处理。apache

那么Web Server和处理工具(这里的php-fpm)是怎样进行交互的呢?传输的是那些数据呢?这些数据的格式又是怎样的呢?windows

由此便引出了今天的主角:CGIapi

1.关于CGI

1.1.什么是CGI?

1)CGI(Common Gateway Interface)全称是“通用网关接口”,是一种让客户端(web浏览器)与Web服务器(nginx等)程序进行通讯(数据传输)的协议。浏览器

用来规范web服务器传输到php解释器中的数据类型以及数据格式,包括URL、查询字符串、POST数据、HTTP header等,也就是为了保证web server传递过来的数据是标准格式的。

2)CGI能够用任何一种具备标准输入、输出和环境变量的语言编写,如php、perl、tcl等。

不一样类型语言写的程序只要符合cgi标准,就能做为一个cgi程序与web服务器交互,早期的cgi大多都是c或c++编写的。

3)通常说的CGI指的是用各类语言编写的能实现该功能的程序。

1.2.CGI程序的工做原理

1)每次当web server收到index.php这种类型的动态请求后,会启动对应的CGI程序(PHP的解析器);
2)PHP解析器会解析php.ini配置文件,初始化运行环境,而后处理请求,处理完成后将数据按照CGI规定的格式返回给web server而后退出进程;
3)最后web server再把结果返回给浏览器。

1.3.CGI程序的特色

1)高并发时的性能较差:
     CGI程序的每一次web请求都会有启动和退出过程,也就是最为人诟病的fork-and-execute模式(每次HTTP服务器遇到动态请求时都须要从新启动脚本解析器来解析php.ini,从新载入所有DLL扩展并重初始化所有数据结构,而后把结果返回给HTTP服务器),很明显,这样的接口方式会致使php的性能不好,在处理高并发访问时,几乎是不可用的。
2)传统的CGI接口方式安全性较差

3)CGI对php.ini的配置很敏感,在开发和调试的时候至关方便

1.4.CGI程序的应用领域

     由于CGI为每一次请求增长一个进程,效率很低,因此基本已经不在生产部署时采用。但因为CGI对php配置的敏感性,一般被用在开发和调试阶段

2.关于FastCGI

2.1.什么是FastCGI?

经过CGI程序的工做原理能够看出:CGI程序性能较差,安全性较低,为了解决这些问题产生了FastCGI。

1)FastCGI(Fast Common Gateway Interface)全称是“快速通用网关接口”
     是通用网关接口(CGI)的加强版本,由CGI发展改进而来,主要用来提升CGI程序性能,
     相似于CGI,FastCGI也是一种让交互程序与Web服务器通讯的协议
2)FastCGI致力于减小网页服务器与CGI程序之间互动的开销,从而使服务器能够同时处理更多的网页请求(提升并发访问)。

3)一样的,通常说的FastCGI指的也是用各类语言编写的能实现该功能的程序。

2.2.FastCGI程序的工做原理

1)Web Server启动同时,加载FastCGI进程管理器(nginx的php-fpm或者IIS的ISAPI或Apache的Module)
2)FastCGI进程管理器读取php.ini配置文件,对自身进行初始化,启动多个CGI解释器进程(php-cgi),等待来自Web Server的链接。
3)当Web Server接收到客户端请求时,FastCGI进程管理器选择并链接到一个CGI解释器。Web server会将相关环境变量和标准输入发送到FastCGI子进程php-cgi进行处理
4)FastCGI子进程完成处理后将数据按照CGI规定的格式返回给Web Server,而后关闭FastCGI子进程或者等待下一次请求。

2.3.FastCGI对进程的管理方式

Fastcgi会先启一个master,解析配置文件,初始化执行环境,而后再启动多个worker。当请求过来时,master会传递给一个worker,而后当即能够接受下一个请求。这样就避免了重复的劳动,效率天然提升。并且当worker不够用时,master能够根据配置预先启动几个worker等着;固然空闲worker太多时,也会停掉一些,这样就提升了性能,也节约了资源。这就是fastcgi的对进程的管理。

2.4.FastCGI的特色:

1)FastCGI具备语言无关性,支持用大多数语言进行编写,对应的程序也支持大多数主流的web服务器
      FastCGI技术目前支持语言有:C/C++,Java,PHP,Perl,Tcl,Python,SmallTalk,Ruby等。
      支持FastCGI技术的主流web服务器有:Apache,Nginx,lighttpd等

2)FastCGI程序的接口方式采用C/S结构,能够将web服务器和脚本解析服务器分开,独立于web服务器运行,提升web服务器的并发性能和安全性:

      提升性能:这种方式支持多个web分发服务器和多个脚本解析服务器的分布式架构,同时能够在脚本解析服务器上启动一个或者多个脚本解析守护进程来处理动态请求,可让web服务器专注地处理静态请求或者将动态脚本服务器的结果返回给客户端,这在很大程度上提升了整个应用系统的性能。

      提升安全性:API方式把应用程序的代码与核心的web服务器连接在一块儿,这时一个错误的API的应用程序可能会损坏其余应用程序或核心服务器,恶意的API的应用程序代码甚至能够窃取另外一个应用程序或核心服务器的密钥,采用这种方式能够在很大程度上避免这个问题

3)FastCGI的不依赖于任何Web服务器的内部架构,所以即便服务器技术的变化, FastCGI依然稳定不变

4)FastCGI程序在修改php.ini配置时能够进行平滑重启加载新配置

      全部的配置加载都只在FastCGI进程启动时发生一次,每次修改php.ini配置文件,只须要重启FastCGI程序(php-fpm等)便可完成平滑加载新配置,已有的动态请求会继续处理,处理完成关闭进程,新来的请求使用新加载的配置和变量进行处理

5)FAST-CGI是较新的标准,架构上和CGI大为不一样,是用一个驻留内存的服务进程向网站服务器提供脚本服务。像是一个常驻(long-live)型的CGI,维护的是一个进程池,它能够一直执行着,只要激活后,不会每次都要花费时间去fork一次(这是CGI最为人诟病的fork-and-execute 模式),速度和效率比CGI大为提升,是目前的主流部署方式。

6)FastCGI的不足:

      由于是在内存中同时运行多进程,因此会比CGI方式消耗更多的服务器内存,每一个PHP-CGI进程消耗7至25兆内存,在进行优化配置php-cgi进程池的数量时要注意系统内存,防止过量

2.5.FastCGI程序的应用领域

     生产环境的主流部署方式

2.6.关于CGI和FastCGI的总结

1)CGI 和 FastCGI 都只是一种通讯协议规范,不是一个实体,通常说的CGI指的是用各类语言编写的能实现该功能的程序
2)CGI 程序和FastCGI程序,是指实现这两个协议的程序,能够是任何语言实现这个协议的。(PHP-CGI 和 PHP-FPM就是实现FastCGI的程序)
3)CGI程序和FastCGI程序的区别:
关于CGI程序:
CGI使外部程序与Web服务器之间交互成为可能。CGI程序运行在独立的进程中,并对每一个Web请求创建一个进程,这种方法很是容易实现,但效率不好,难以扩展。面对大量请求,进程的大量创建和消亡使操做系统性能大大降低。此外,因为地址空间没法共享,也限制了资源重用。

关于FastCGI程序:
与CGI程序为每一个请求建立一个新的进程不一样,FastCGI使用持续的进程(master)来处理一连串的请求。这些进程由FastCGI服务器管理,而不是web服务器。 当进来一个请求时,web服务器把环境变量和这个页面请求经过一个socket或者一个TCP connection传递给FastCGI进程。

3.关于PHP-CGI,PHP-FPM和Spawn-FCGI

3.1.PHP-CGI是什么?

   不少地方说:PHP-CGI是PHP自带的FastCGI管理器,目前还没找到最原始的出处,以个人理解和经验来看这话有点毛病,我认为应该是:使用php实现CGI协议的CGI程序,能够用来管理php解释器,若是有异议能够和我探讨下。。。

使用以下命令能够启动PHP-CGI:

php-cgi -b 127.0.0.1:9000

php-cgi的特色:

1)php-cgi变动php.ini配置后需重启php-cgi才能让新的配置生效,不能够平滑重启

2)直接杀死php-cgi进程php就不能运行了

3.2.关于php-fpm

PHP-FPM(FastCGI Process Manager)

针对PHP-CGI的不足,PHP-FPM和Spawn-FCGI应运而生,它们的守护进程会平滑重新生成新的子进程。 

1)PHP-FPM使用PHP编写的PHP-FastCGI管理器,管理对象是PHP-CGI程序,不能说php-fpm是fastcgi进程的管理器,由于前面说了fastcgi是个协议

下载地址:http://php-fpm.org/download

早期的PHP-FPM是做为PHP源码的补丁而使用的,在PHP的5.3.2版本中直接整合到了PHP-FPM分支,目前主流的PHP5.5,PHP5.6,PHP5.7已经集成了该功能(被官方收录)

在配置时使用--enable-fpm参数便可开启PHP-FPM

2)修改php.ini以后,php-cgi进程的确是没办法平滑重启的。php-fpm对此的处理机制是新的worker用新的配置,已经存在的worker处理完手上的活就能够歇着了,经过这种机制来平滑过分。

3.3.关于Spawn-FCGI

1)Spawn-FCGI是一个通用的FastCGI管理服务器,它是lighttpd中的一部份,不少人都用Lighttpd的Spawn-FCGI进行FastCGI模式下的管理工做

2)Spawn-FCGI目前已经独成为一个项目,更加稳定一些,也给不少Web 站点的配置带来便利。已经有很多站点将它与nginx搭配来解决动态网页。

Spawn-FCGI的下载地址是http://redmine.lighttpd.net/projects/spawn-fcgi,目前(20190114)最新版本为1.6.4,在4年前更新的,有点凉凉的意思。。。

3.4.PHP-FPM与spawn-CGI对比

1)PHP-FPM的配置都是在php-fpm.ini的文件内,早些时候重启能够经过/usr/local/php/sbin/php-fpm reload进行,无需杀掉进程就能够完成php.ini的修改加载,被php官方收录之后须要指定参数进行重载配置,能够本身建立脚本进行管理
2)PHP-FPM控制的进程cpu回收的速度比较慢,内存分配的很均匀,比Spawn-FCGI要好,能够有效控制内存和进程,且不容易崩溃,很优秀
3)Spawn-FCGI控制的进程CPU降低的很快,而内存分配的比较不均匀。有不少进程彷佛未分配到,而另一些却占用很高。多是因为进程任务分配的不均匀致使的。而这也致使了整体响应速度的降低。而PHP-FPM合理的分配,致使整体响应的提到以及任务的平均。

(摘录的,暂未实际验证)

4.PHP运行的5种模式

php目前比较常见的五大运行模式:包括cli、cgi 、fast-cgi、isapi、apache模块的DLL 

4.1.cli模式

cli模式就是php的命令行运行模式,

例如:在linux下常用 “php -m”查找PHP安装了那些扩展就是PHP命令行运行模式

其余的能够输入php -h查看下

4.2.CGI模式

比较经典的使用方法,使用CGI程序将浏览器,web服务器,php解释器链接起来进行数据交换的工具,目前主要用来作开发或调试

CGI方式在遇到链接请求(用户 请求)先要建立cgi的子进程,激活一个CGI进程,而后处理请求,处理完后结束这个子进程。这就是fork-and-execute模式。因此用cgi方式的服务器有多少链接请求就会有多少cgi子进程,子进程反复加载是cgi性能低下的主要缘由。都会当用户请求数量很是多时,会大量挤占系统的资源如内 存,CPU时间等,形成效能低下。

4.3.FastCGI模式

目前主流的使用方式,比CGI模式的工具效率高不少,大量用于分布式高并发的环境中

在Linux中,nginx加php-fpm是最主流的使用方式

4.4.ISAPI运行模式

ISAPI即Internet Server Application Program Interface,是微软提供的一套面向Internet服务的API接口,一个ISAPI的DLL,能够在被用户请求激活后长驻内存,等待用户的另外一个请求,还能够在一个DLL里设置多个用户请求处理函数,此外,ISAPI的DLL应用程序和WWW服务器处于同一个进程中,效率要显著高于CGI。(因为微软的排他性,只能运行于windows环境)

4.5.apache模块运行模式

此运行模式能够在Linux和windows环境下使用Apache,他们的共同点都是用 LoadModule 来加载相关模块,有两种类型

4.5.1.mod_php模块

Apache调用php的相关模块(php5_module),也就是把php做为apache的一个子模块来运行

当经过web访问php文件时,apache就会调用php5_module经过sapi将数据传给php解析器来解析php代码,整个过程以下图:

从上面图中,能够看出:

1)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

2)apache每接收一个请求,都会产生一个进程来链接php经过sapi来完成请求,若是用户过多,并发数过多,服务器就会承受不住了。

3)把mod_php编进apache时,出问题时很难定位是php的问题仍是apache的问题,并且PHP是与Web服务器一块儿启动并运行的,当php模块出现问题可能会致使Apache一同挂掉

4.5.2.mod_cgi模块

在此种模式中Apache启动加载mod_cgi模块,使用CGI调用管理动态的php请求

更高级的是mod_fcgid模块,是apache的fastcgi实现,性能提升,在apache的2.4之后的版本中获得支持。

总结:

1)mod_php是apache的内置php解释模块,使用prefork方式,不须要额外的进程来作通信和应用解释,显然mod_php比mod_cgi这样方式性能要好得多

2)缺点是把应用和HTTP服务器绑定在了一块儿,当php模块出现问题可能会致使Apache一同挂掉

3)另外每一个Apache进程都须要加载mod_php而不论这个请求是处理静态内容仍是动态内容,这样致使浪费内存,效率降低,

4)php.ini文件的变动须要从新启动apache服务器才能生效,这使得没法进行平滑配置变动。

4.6.总结一下

随着技术的不断升级,单纯的Apache加php模块的方式已再也不主流,而是替换为Apache加php_cgi,以及后来的php_fcgi和nginx加php-fpm的方法,能够看下图:

5.参考文章:

CGI、FastCGI和PHP-FPM关系图解:https://www.awaimai.com/371.html

关于CGI 和 PHP-FPM须要弄清的:http://www.cleey.com/blog/single/id/848.html

浅谈PHP fastcgi和php-fpm:https://www.jianshu.com/p/d095cbcbcf1b

php五大运行模式CGI,FAST-CGI,CLI,ISAPI,APACHE模式浅谈:http://www.javashuo.com/article/p-nxopduuv-cd.html

==== 完毕,呵呵呵呵 ====

相关文章
相关标签/搜索