聊聊CGI、FastCGI、WSGI
CGI
CGI(Common Gateway Interface,通用网关接口 ),描述了服务器和客户端请求处理程序(通常就是浏览器)之间传输数据的一种标准。
它最初是在1993年由NCSA(美国国家超级电脑应用中心)为NCSA HTTPd Web服务器开发的。
CGI的第一个实现是采用Perl编写的。Perl被广泛用于编写CGI程序,但CGI本身是独立于任何语言的。事实上,CGI程序可以使用任何脚本语言甚至是编译型语言分别独立实现,比如Unix Shell、Python、Ruby、PHP、C/C++等。
CGI的工作方式大致可以描述为:
- Step0 普通用户通过浏览器(或者是表单提交、或者是直接访问URL)发送请求给Web服务器
- Step1 Web服务器接收到请求后,启动CGI程序,通过环境变量、标准输入等传递数据,将请求转交给对应的CGI进程
- Step2 CGI进程启动解析器,或者访问数据库、或者完成相关计算、或者与其它第三方进行交互
- Step3 在CGI程序处理完成后,通过标准输出将处理结果返回给Web服务器
- Step4 Web服务器收到结果后,构建Response返回给客户端,并杀死CGI进程
总结来说,CGI采用的是“fork-and-execute”的工作模式,其缺点在于:效率低下,每个请求都需要fork一个新的CGI进程去处理。当请求量增大时服务器很快将被压垮。
为了提升CGI工作性能,有一种办法是,将脚本解释器直接作为模块集成在Web服务器中,例如:Apache的mod_perl模块,这样就能够避免重复载入和初始化解释器。不过这只是针对那些解释型语言而言的,使用诸如C一类的编译型语言则可以避免这种额外负荷。由于C及其他编译语言的程序与解释语言程序相比,前者的运行速度更快、对操作系统的负荷更小,使用编译语言程序是可能达到更高执行效率的。然而因为开发效率等因素,在目前解释型语言还是最合适的。
另一个办法就是FastCGI技术。
FastCGI
FastCGI(快速通用网关接口),是CGI的增强版本。其目的在于,减少Web服务器与CGI程序之间交互的开销,使得服务器可以同时处理更多的请求。
与CGI“fork-and-execute”的工作模式不同,FastCGI像是一个常驻型的CGI,它使用持续的进程来处理一连串的请求。这些进程由FastCGI进程管理器管理,而不是Web服务器。当进来一个请求时,Web服务器把环境变量和这个页面请求通过一个unix domain socket(比如FastCGI进程与Web服务器都位于本地)或者一个TCP连接(FastCGI进程部署在远端)传递给FastCGI进程。
- Step1 Web服务器启动时,初始化FastCGI执行环境,例如apache mod_fastcgi、nginx ngx_http_fastcgi_module、lighttpd mod_fastcgi
- Step2 FastCGI进程管理器自身初始化,启动多个CGI解释器进程并等待来自Web服务器的连接
- Step3 当客户端请求到达Web服务器时,Web服务器将请求通过socket方式转发到FastCGI主进程,主进程选择并连接到一个CGI解释器。Web服务器将CGI环境变量和标准输入发送到FastCGI子进程
- Step4 FastCGI子进程完成处理后,将标准输出和错误信息通过同一socket返回给Web服务器,并关闭连接
- Step5 FastCGI子进程接着等待下一个新的连接
不足之处:
PHP-CGI
PHP-CGI是PHP自带的FastCGI管理器。
不足之处:
- 变更php.ini配置后,需重启PHP-CGI才能生效,不能平滑重启
- 直接杀死PHP-CGI进程,PHP就不能运行了(PHP-FPM和Spawn-FCGI就没有这个问题了,守护进程会平滑地重新生成新的子进程)
PHP-FPM
PHP-FPM是一个PHP FastCGI管理器,最初它只是PHP源码的一个补丁,而从PHP 5.3.3开始,已经被集成到了PHP源码中。与原生的PHP-CGI相比,它提供了更加友好的管理方式,可以有效控制内存和进程、可以平滑重载PHP配置。
Spawn-FCGI
Spawn-FCGI是一个通用的FastCGI管理器,起初它是lighttpd的一部分。目前,Spawn-FCGI已经独立成为一个项目,性能较以往更加稳定。
WSGI
But,事情总是还有改进的余地的,FastCGI这套工作模式实际上没有什么太大缺陷,但是有些不安分的Python程序猿觉得,FastCGI标准下写异步的Web服务还是不太方便,如果能够收到请求后CGI端去处理,处理完毕后通过Callback回调来返回结果,那样岂不是很Coooool?!所以WSGI就被创造出来了:
以上引文很好地说明了WSGI的来历。WSGI(Web Server Gateway Interface)是专门为Python定义的Web服务器和Web应用程序或框架之间的一种简单而通用的接口。
其工作方式大致是:当Web服务器接收到一个请求后,可以通过Socket把环境变量和一个callback回调函数传递给后端Web应用程序,Web应用程序处理完成后,调用callback函数,把结果返回给WebServer。
这种方式的优点有:
- 异步化,通过callback将Web请求的工作拆解开,可以很方便地在一个线程空间里同时处理多个Web请求
- 方便进行各种负载均衡和请求转发,不会造成后端Web应用阻塞
参考资料: