如何理解 CGI, WSGI?

关注者
840
被浏览
175,992

22 个回答

正好最近在学习CGI。

CGI是比较原始的开发动态网站的方式。你可以想象一下,一个网站的动态内容肯定是程序生成的,光是静态的html页面无法达到这个效果。那么,这个程序就需要接受客户端的请求,然后进行相应处理,再返回给客户端,客户端和服务端的通信当然是通过HTTP协议。

然后我们会发现,这个程序在处理客户端请求的时候,大部分时候会进行很多重复的工作,比如说HTTP请求的解析。也就是说,你的程序需要解析HTTP请求,我的程序也需要解析。

于是为了DRY原则,Web服务器诞生了。(以下所说的都是CGI的工作模式)

于是Web服务器可以解析这个HTTP请求,然后把这个请求的各种参数写进进程的环境变量,比如

REQUEST_METHOD,PATH_INFO之类的。之后呢,服务器会调用相应的程序来处理这个请求,这个程序也就是我们所要写的CGI程序了。它会负责生成动态内容,然后返回给服务器,再由服务器转交给客户端。服务器和CGI程序之间通信,一般是通过进程的环境变量和管道。

这样做虽然很清晰,但缺点就是每次有请求,服务器都会fork and exec,每次都会有一个新的进程产生,开销还是比较大的。

原因在与CGI程序是一个独立的程序,它是可以独立运行的(在提供HTTP请求的情况下),它可以用几乎所有语言来写,包括perl,c,lua,python等等。所以对于一个程序,服务器只能以fork and exec的方式来调用它了。

我所理解的CGI差不多就是这样。

搜索CGI资料的的百分之八十是腾讯程序员吧。

言归正传

CGI,一言以蔽之——协议。为了和普通的网络协议做区分,我们可以称之为接口协议。所谓协议就是各方约定,达成共识的一种规则。比如中国公路靠右行驶,这就是公路的协议。网络协议约定的是逐字节的含义,大家遵守,就能方便解析,理解。CGI约定的不是逐字节的语义,而是一个个kv(不完全是kv,但可以大概这么理解)。用一个不太恰当的比喻来形容,网络协议描述的单位是数组,而CGI接口协议描述的是map。
CGI是古老的web技术,在php这类动态网页语言出现之前承担过一个时期的历史任务。当时多是用perl或c来编写CGI程序。前端通过表单可以向服务器(比如Apache)发送一个URL。Apache可以获取到很多参数(get或post请求的参数、服务器和客服端的信息,cookie等等)。Apache在开启 了cgi模块以后可以将参数存到环境变量中,并调用一个CGI程序,这个程序可以是各种语言,比如c++(或c语言)就是从环境变量中解析出这样请求的具体参数。然后向标准输出输出内容(比如printf或cout了一段HTML代码),这些内容没有被打印到控制台上,而是被执行了标注输出fd的重定向,定向给了套接字,最终发送到了你的浏览器。浏览器收到http请求,解析html代码,然后渲染出了网页。重要一点是CGI程序记得要自己先输出http报头哦。

缺点是每一次向CGI发送请求,都会生成一个CGI进程,这种就是所谓的fork-and-exec模式,也就是导致并发瓶颈的症结。或许反向代理加上大型的的分布式系统可以一定程度上减轻这些压力。但是随意JAVA为代表的动态web解决方案的出现,CGI未老先衰,早早被扫进了历史的尘埃中。
大浪淘沙,如今CGI几乎消失在了人们的视野中,然而它确是让你了解很多web底层知识的好工具。近年来由于fcgi的出现,一直以来被人们所诟病的fork-and-exec问题得到解决,使得CGI多少又浮出了一点水面。
顺带一提,腾讯几乎是是国内硕果仅存的使用c++和CGI做web接入层(不是全部业务采用cgi)的公司了,这主要是由于历史原因吧。 大学生朋友们,如果应聘腾讯看到后台工程师的技能要求是c++,千万不要惊讶。看到php是前端工程师的要求也别奇怪,毕竟c++直接cout出来HTML还是略蛋疼,php做这层view应该是一种高效的解决方案吧。当然不加php,前端直接对接后台c++也是不奇怪的,毕竟restful的风格走俏嘛!

手机码字不易,且赞且珍惜。特别是腾讯的朋友。