CGI是什么

CGI

早期的Web服务器,只能响应浏览器发来的HTTP静态资源的请求,并将存储在服务器中的静态资源返回给浏览器。随着Web技术的发展,逐渐出现了动态技术,但是Web服务器并不能够直接运行动态脚本,为了解决Web服务器与外部应用程序(CGI程序)之间数据互通,于是出现了CGI(Common Gateway Interface)通用网关接口。简单理解,可以认为CGI是Web服务器和运行其上的应用程序进行“交流”的一种约定。

Web系统结构

CGI是Web服务器和一个独立的进程之间的协议,它会把HTTP请求RequestHeader头设置成进程的环境变量,HTTP请求的Body正文设置成进程的标准输入,进程的标准输出设置为HTTP响应Response,包含Header头和Body正文。

CGI

CGI 程序

CGI只是一个接口规范或协议,它的实现则与具体的编程语言相关。在2000年以前,CGI通用网关接口盛行,那个时候,Perl是编写CGI的主流语言,以至于一般的CGI程序都是Perl程序。

CGI程序

通过CGI接口,Web服务器就能够获取客户端传递的数据,并转交给服务器端的CGI程序处理,然后返回结果给客户端。简单来说,CGI实际上是一个接口标准。而通常所说的CGI指代其实是CGI程序,也就是实现了CGI接口标准的程序,只要编程语言具有标准输入、标准输出和环境变量,就可以用来编写CGI程序。

CGI程序通过标准输入(STDIN)和标准输出(STDOUT)进行数据的输入输出,此外CGI程序还通过环境变量来得到输入,操作系统提供了许多环境变量,它们定义了程序的执行环境,应用程序可以存取它们。Web服务器和CGI接口又另外设置了一些环境变量,用来向CGI程序传递一些重要的参数。CGI的GET方法还通过环境变量QUERY_STRING向CGI程序传递Form表单中的数据。

CGI工作概要

对于一个CGI程序,主要的工作是从环境变量和标准输入中读取数据,然后处理数据,最后向标准输出中输出数据。

  • 环境变量
    环境变量中存储的叫做Request Meta-Variables,也就是诸如QUERY_STRINGPATH_INFO之类的,这些都是由Web服务器通过环境变量传递给CGI程序的,CGI程序也是从环境变量中读取的。
  • 标准输出
    中存放的往往是用户通过PUTSPOST提交的数据,这些数据也是由Web服务器传递过来的。

为了处理动态请求,Web服务器会根据请求的内容,Fork创建一个新进程来运行外部C程序或Perl脚本等,这个进程会把处理完的数据返回给Web服务器,然后Web服务器把内容发送给用户,Fork创建出来的进程也会随之退出。如果下次用户请求为动态脚本,那么Web服务器会再次Fork创建一个新进程,如此周而复始的运行。


CGI

以Nginx接收HTTP请求为例,Nginx接收一个HTTP请求后Fork创建出一个进程,将HTTP请求带来的参数作为输入,执行完程序处理后输出,最终会摧毁这个Fork出来的进程,并将输出返回给客户端。这种方式虽然简单,但是需要不断地Fork进程和销毁进程。

CGI协议

CGI程序的工作原理

Web服务器一般只用来处理静态文件请求,一旦碰到动态脚本请求,Web服务器主进程就会Fork创建出一个新的进程来启动CGI程序,也就是将动态脚本交给CGI程序来处理。启动CGI程序需要一个过程,如读取配置文件、加载扩展等。当CGI程序启动后会去解析动态脚本,然后将结果返回给Web服务器,最后由Web服务器将结果返回给客户端,之前Fork出来的进程也随之关闭。这样,每次用户请求动态脚本,Web服务器都要重新Fork创建一个新进程去启动CGI程序,由CGI程序来处理动态脚本,处理完成后进程随之关闭,其效率是非常低下的。

CGI程序工作原理

PHP-CGI

CGI是一个协议,PHP语言对CGI接口规范的实现也就是PHP-CGI,也就是PHP的解释器。随着技术的发展,PHP-CGI的性能问题逐渐暴露,不是那么尽如人意。PHP在运行的时候是依赖配置文件php.ini的,所以每当PHP-CGI开始工作的时候,它完全是一个新进程,需要重新加载PHP配置文件并初始化,这就造成了很大的资源和时间的浪费。

PHP-CGI

每当客户端请求CGI时,Web服务器就会请求操作系统生成一个新的CGI解释器进程php-cgi.exe,CGI的一个进程处理完一个请求后退出,下一个请求来时在先操作系统申请创建新进程。在访问量较少没有并发的情况下这样做是没有问题的,一旦出现访问量增大,并发出现时这种方式就不再合适了,于是便出现了FastCGI。

Web服务器内置模块

后来出现了一种比较高效的方式:Web服务器内置模块。例如,Apache的mod_php模块,将PHP解释器做成模块加载到Apache服务器中。这样,Apache服务器在启动的时候,就会同时启动PHP模块。当客户端请求PHP文件时,Apache就不用再Fork创建出一个新进程来启动PHP解释器,而是直接将PHP文件交给运行中的PHP模块处理。显然这种方式下,效率会比较高。由于在Apache服务器启动时,才会读取PHP的配置文件,加载PHP模块。在Apache运行过程中,不会在重新读取PHP配置文件。所以,每次修改PHP的配置文件php.ini后,必须重启Apache,新的PHP配置文件才会生效。

FastCGI

FastCGI是Web服务器与处理程序之间通信的一种协议,是CGI的改进版本。由于CGI程序反复加载CGI而造成性能低下,如果CGI程序保持在内存中并接收FastCGI进程管理器调度,则可以提供良好的性能、伸缩性、Fail-Over特性等。

FastCGI就是常驻型的CGI,可以一直运行。在请求到达时不会耗费时间去Fork创建一个进程来处理。FastCGI是语言无关的、可伸缩架构的CGI开放扩展,它将CGI解释器进程保持在内存中,因此获得较高的性能。

FastCGI的工作流程

1.Web服务器启动时载入FastCGI进程管理,如IIS的ISAPI、Apache的Module...

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

PHP-FPM

FastCGI是一个协议,PHP-FPM实现了这个协议。FastCGI是CGI的改进版,它是一个常驻内存的CGI服务。常用的PHP-FPM就是在这种模式下运行的,PHP-FPM负责Fork多个进程,每个进程都运行着PHP解释器。

PHP-FPM

在Nginx+PHP-FPM的组合中,Nginx负责接收HTTP请求并将请求封装好交给PHP-FPM,PHP-FPM将请求按照一定的规则交给一个子进程去处理,这个子进程中的PHP解释器会加载PHP代码,也是因为这个原因,传统的PHP只能作为Web服务器。我们发现,Nginx+PHP-FPM的组合和Reactor+Worker子进程的组合非常类似。

PHP的解释器PHP-CGI只是一个CGI程序,它本身只能解析请求并返回结果,不会对进程进行管理,所以就出现了一些能够调度PHP-CGI进程的程序。PHP-FPM是PHP对FastCGI的一种具体实现,是fast-cgi进程管理工具。PHP-FPM启动后会创建多个CGI子进程,然后主进程负责管理子进程,同时对外提供一个socket,那么Web服务器当要转发一个动态请求时,只需要按照FastCGI协议要求的格式将数据发往socket即可。PHP-FPM创建的子进程去争夺socket连接,谁抢到谁处理并将结果返回给Web服务器。当其中一个子进程异常退出时,PHP-FPM主进程会去监控,一旦发现CGI子进程就会又启动一个。

CGI、FastCGI、PHP-FPM

Swoole

以Swoole作为HTTP服务器为例,首先Swoole内部实现了HTTP服务器,也就不需要使用Nginx作为HTTP服务器,当然Swoole并不是为了取代Nginx,实际上Swoole当前实现的HTTP的功能非常有限,比如说只支持GET和POST,所以往往Swoole前面还要运行一个Nginx作为前端的代理服务器。

Swoole是常驻内存的,这一点和PHP-FPM不同,PHP-FPM中常驻的是PHP解释器,PHP解释器会重复加载PHP代码并初始化环境。而Swoole只是在启动的时候加载。如此一来性能自然会提高,这一点在开发中体现的比较明显,例如在PHP-FPM下修改PHP代码是会即时生效的,而在Swoole中式需要重启Swoole的服务器才能使代码生效。

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

推荐阅读更多精彩内容