【技术分享】网关协议学习:CGI、FastCGI、WSGI

CGIphp

CGI即通用网关接口(Common Gateway Interface),是外部应用程序(CGI程序)与Web服务器之间的接口标准,是在CGI程序和Web服务器之间传递信息的规程。CGI规范容许Web服务器执行外部程序,并将它们的输出发送给Web浏览器,CGI将Web的一组简单的静态超媒体文档变成一个完整的新的交互式媒体。通俗的讲CGI就像是一座桥,把网页和WEB服务器中的执行程序链接起来,它把HTML接收的指令传递给服务器的执行程序,再把服务器执行程序的结果返还给HTML页。CGI 的跨平台性能极佳,几乎能够在任何操做系统上实现。html

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

CGI脚本工做流程:git

  1. 浏览器经过HTML表单或超连接请求指向一个CGI应用程序的URL。
  2. 服务器收发到请求。
  3. 服务器执行所指定的CGI应用程序。
  4. CGI应用程序执行所须要的操做,一般是基于浏览者输入的内容。
  5. CGI应用程序把结果格式化为网络服务器和浏览器可以理解的文档(一般是HTML网页)。
  6. 网络服务器把结果返回到浏览器中。

FastCGIgithub

FastCGI是一个可伸缩地、高速地在HTTP server和动态脚本语言间通讯的接口。多数流行的HTTP server都支持FastCGI,包括Apache、Nginx和lighttpd等,同时,FastCGI也被许多脚本语言所支持,其中就有PHP。web

FastCGI是从CGI发展改进而来的。传统CGI接口方式的主要缺点是性能不好,由于每次HTTP服务器遇到动态程序时都须要从新启动脚本解析器来执行解析,而后结果被返回给HTTP服务器。这在处理高并发访问时,几乎是不可用的。FastCGI像是一个常驻(long-live)型的CGI,它能够一直执行着,只要激活后,不会每次都要花费时间去fork一次(这是CGI最为人诟病的fork-and-execute 模式)。CGI 就是所谓的短生存期应用程序,FastCGI 就是所谓的长生存期应用程序。因为 FastCGI 程序并不须要不断的产生新进程,能够大大下降服务器的压力而且产生较高的应用效率。它的速度效率最少要比CGI 技术提升 5 倍以上。它还支持分布式的运算, 即 FastCGI 程序能够在网站服务器之外的主机上执行而且接受来自其它网站服务器来的请求。数据库

FastCGI是语言无关的、可伸缩架构的CGI开放扩展,其主要行为是将CGI解释器进程保持在内存中并所以得到较高的性能。众所周知,CGI解释器的反复加载是CGI性能低下的主要缘由,若是CGI解释器保持在内存中并接受FastCGI进程管理器调度,则能够提供良好的性能、伸缩性、Fail-Over特性等等。FastCGI接口方式采用C/S结构,能够将HTTP服务器和脚本解析服务器分开,同时在脚本解析服务器上启动一个或者多个脚本解析守护进程。当HTTP服务器每次遇到动态程序时,能够将其直接交付给FastCGI进程来执行,而后将获得的结果返回给浏览器。这种方式可让HTTP服务器专注地处理静态请求或者将动态脚本服务器的结果返回给客户端,这在很大程度上提升了整个应用系统的性能。apache

FastCGI的工做流程:编程

  1. Web Server启动时载入FastCGI进程管理器(PHP-CGI或者PHP-FPM或者spawn-cgi)
  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 的特色windows

  1. 打破传统页面处理技术。传统的页面处理技术,程序必须与 Web 服务器或 Application 服务器处于同一台服务器中。这种历史已经早N年被FastCGI技术所打破,FastCGI技术的应用程序能够被安装在服务器群中的任何一台服务器,而经过 TCP/IP 协议与 Web 服务器通信,这样作既适合开发大型分布式 Web 群,也适合高效数据库控制。
  2. 明确的请求模式。CGI 技术没有一个明确的角色,在 FastCGI 程序中,程序被赋予明确的角色(响应器角色、认证器角色、过滤器角色)。

ISAPI

ISAPI(Internet Server Application Program Interface)是微软提供的一套面向WEB服务的API接口,它能实现CGI提供的所有功能,并在此基础上进行了扩展,如提供了过滤器应用程序接口。ISAPI应用大多数以DLL动态库的形式使用,能够在被用户请求后执行,在处理完一个用户请求后不会立刻消失,而是继续驻留在内存中等待处理别的用户输入。此外,ISAPI的DLL应用程序和WEB服务器处于同一个进程中,效率要显著高于CGI。(因为微软的排他性,只能运行于windows环境)

ISAPI服务器扩展为使用 Internet 服务器的通用网关接口(CGI) 应用程序提供了另外一种选择。与 CGI 应用程序不一样,ISA 在 HTTP服务器所在的同一地址空间运行,而且能够访问可由 HTTP 服务器使用的全部资源。ISA 的系统开销比 CGI 应用程序低,由于它们不要求建立其余进程,也不执行须要越过进程边界的通讯,而这种通讯很是耗时。若是内存被其余进程所须要,扩展和筛选器DLL 均可能被卸载。ISAPI 容许在一个 DLL 中有多个命令,这些命令做为 DLL 中CHttpServer对象的成员函数来实现。CGI 要求每一个任务有一个单独的名称和一个到单独的可执行文件的 URL 映射。每一个新的 CGI 请求启动一个新进程,而每一个不一样的请求包含在各自的可执行文件中,这些文件根据每一个请求加载和卸载,所以系统开销高于 ISA。

PHP-CGI

PHP-CGI是PHP自带的FastCGI管理器。PHP-CGI的不足:

  1. php-cgi变动php.ini配置后需重启php-cgi才能让新的php-ini生效,不能够平滑重启
  2. 直接杀死php-cgi进程php就不能运行了。(PHP-FPM和Spawn-FCGI就没有这个问题,守护进程会平滑重新生成新的子进程。)

Spawn-FCGI

Spawn-FCGI是一个通用的FastCGI管理服务器,它是lighttpd中的一部份,不少人都用Lighttpd的Spawn-FCGI进行FastCGI模式下的管理工做,不过有很多缺点。而PHP-FPM的出现多少缓解了一些问题,但PHP-FPM有个缺点就是要从新编译,这对于一些已经运行的环境可能有不小的风险),在php 5.3.3中能够直接使用PHP-FPM了。Spawn-FCGI的代码不多,所有才630行,用c语言编写,最近一次提交是5年前。代码主页:https://github.com/lighttpd/spawn-fcgi

Spawn-FCGI代码分析以下:

  1. spawn-fcgi 首先create socket,bind,listen 3步建立服务器socket,(把这个socket叫作 fcgi_fd)
  2. 用dup2,把fcgi_fd 交换给 FCGI_LISTENSOCK_FILENO (FCGI_LISTENSOCK_FILENO数值上等于0,这是fastcgi协议当中指定用来listen的socket id)
  3. 执行execl ,replaces the current process image with a new process image. process image 进程在运行空间的代码段

很显然,Spawn-FCGI也是 pre-fork 模型,只是用了上古C语言编写,充满了N多 unix下暗黑编程技巧。

Spawn-FCGI功能很单一:

  1. 只管fork进程,子进程挂了,主进程仅仅log记录一次,根本不会从新fork。在2009年一段时间内,我曾经用spawn-fcgi部署php-cgi,当跑一段时间就会全挂掉,只能用crontab定时重启spawn-fcgi
  2. 不负责子进程中的网络IO,把socket放到指定位置就完了,接下来的事情由被spawn的程序处理

Spawn-FCGI是一个很早期的程序,瞻仰一下便可。另外有:1996年的一段代码:http://www.fastcgi.com/om_archive/kit/cgi-fcgi/cgi-fcgi.c,和spawn-fcgi一个风格

PHP-FPM

PHP-FPM是一个PHP FastCGI管理器,是只用于PHP的,能够在 http://php-fpm.org/download下载获得。PHP-FPM实际上是PHP源代码的一个补丁,旨在将FastCGI进程管理整合进PHP包中。必须将它patch到你的PHP源代码中,在编译安装PHP后才可使用。FPM(FastCGI 进程管理器)用于替换 PHP-CGI 的大部分附加功能,对于高负载网站是很是有用的。它的功能包括:

  1. 支持平滑中止/启动的高级进程管理功能;
  2. 能够工做于不一样的 uid/gid/chroot 环境下,并监听不一样的端口和使用不一样的 php.ini 配置文件(可取代 safe_mode 的设置);
  3. stdout 和 stderr 日志记录;
  4. 在发生意外状况的时候可以从新启动并缓存被破坏的 opcode;
  5. 文件上传优化支持;
  6. “慢日志” – 记录脚本(不只记录文件名,还记录 PHP backtrace 信息,可使用 ptrace或者相似工具读取和分析远程进程的运行数据)运行所致使的异常缓慢;
  7. fastcgi_finish_request() – 特殊功能:用于在请求完成和刷新数据后,继续在后台执行耗时的工做(录入视频转换、统计处理等);
  8. 动态/静态子进程产生;
  9. 基本 SAPI 运行状态信息(相似Apache的 mod_status);
  10. 基于 php.ini 的配置文件。

WSGI

Web服务器网关接口(Python Web Server Gateway Interface,缩写为WSGI)是为Python语言定义的Web服务器和Web应用程序或框架之间的一种简单而通用的接口。自从WSGI被开发出来之后,许多其它语言中也出现了相似接口。WSGI是做为Web服务器与Web应用程序或应用框架之间的一种低级别的接口,以提高可移植Web应用开发的共同点。WSGI是基于现存的CGI标准而设计的。

WSGI区分为两个部份:一为“服务器”或“网关”,另外一为“应用程序”或“应用框架”。在处理一个WSGI请求时,服务器会为应用程序提供环境资讯及一个回呼函数(Callback Function)。当应用程序完成处理请求后,透过前述的回呼函数,将结果回传给服务器。所谓的 WSGI 中间件同时实现了API的两方,所以能够在WSGI服务和WSGI应用之间起调解做用:从WSGI服务器的角度来讲,中间件扮演应用程序,而从应用程序的角度来讲,中间件扮演服务器。“中间件”组件能够执行如下功能:

  1. 重写环境变量后,根据目标URL,将请求消息路由到不一样的应用对象。
  2. 容许在一个进程中同时运行多个应用程序或应用框架。
  3. 负载均衡和远程处理,经过在网络上转发请求和响应消息。
  4. 进行内容后处理,例如应用XSLT样式表。

之前,如何选择合适的Web应用程序框架成为困扰Python初学者的一个问题,这是由于,通常而言,Web应用框架的选择将限制可用的Web服务器的选择,反之亦然。那时的Python应用程序一般是为CGI,FastCGI,mod_python中的一个而设计,甚至是为特定Web服务器的自定义的API接口而设计的。WSGI没有官方的实现, 由于WSGI更像一个协议。只要遵守这些协议,WSGI应用(Application)均可以在任何服务器(Server)上运行, 反之亦然。WSGI就是Python的CGI包装,相对于Fastcgi是PHP的CGI包装。

WSGI将 web 组件分为三类: web服务器,web中间件,web应用程序, wsgi基本处理模式为 : WSGI Server -> (WSGI Middleware)* -> WSGI Application 。

wsgi

一、WSGI Server/gateway

wsgi server能够理解为一个符合wsgi规范的web server,接收request请求,封装一系列环境变量,按照wsgi规范调用注册的wsgi app,最后将response返回给客户端。文字很难解释清楚wsgi server究竟是什么东西,以及作些什么事情,最直观的方式仍是看wsgi server的实现代码。以python自带的wsgiref为例,wsgiref是按照wsgi规范实现的一个简单wsgi server。它的代码也不复杂。

wsgi-gateway

  1. 服务器建立socket,监听端口,等待客户端链接。
  2. 当有请求来时,服务器解析客户端信息放到环境变量environ中,并调用绑定的handler来处理请求。
  3. handler解析这个http请求,将请求信息例如method,path等放到environ中。
  4. wsgi handler再将一些服务器端信息也放到environ中,最后服务器信息,客户端信息,本次请求信息所有都保存到了环境变量environ中。
  5. wsgi handler 调用注册的wsgi app,并将environ和回调函数传给wsgi app
  6. wsgi app 将reponse header/status/body 回传给wsgi handler
  7. 最终handler仍是经过socket将response信息塞回给客户端。

二、WSGI Application

wsgi application就是一个普通的callable对象,当有请求到来时,wsgi server会调用这个wsgi app。这个对象接收两个参数,一般为environ,start_response。environ就像前面介绍的,能够理解为环境变量,跟一次请求相关的全部信息都保存在了这个环境变量中,包括服务器信息,客户端信息,请求信息。start_response是一个callback函数,wsgi application经过调用start_response,将response headers/status 返回给wsgi server。此外这个wsgi app会return 一个iterator对象 ,这个iterator就是response body。这么空讲感受很虚,对着下面这个简单的例子看就明白不少了。

三、WSGI MiddleWare

有些功能可能介于服务器程序和应用程序之间,例如,服务器拿到了客户端请求的URL, 不一样的URL须要交由不一样的函数处理,这个功能叫作 URL Routing,这个功能就能够放在两者中间实现,这个中间层就是 middleware。middleware对服务器程序和应用是透明的,也就是说,服务器程序觉得它就是应用程序,而应用程序觉得它就是服务器。这就告诉咱们,middleware须要把本身假装成一个服务器,接受应用程序,调用它,同时middleware还须要把本身假装成一个应用程序,传给服务器程序。

其实不管是服务器程序,middleware 仍是应用程序,都在服务端,为客户端提供服务,之因此把他们抽象成不一样层,就是为了控制复杂度,使得每一次都不太复杂,各司其职。

参考资料:

uWCGI

uWSGI 项目旨在为部署分布式集群的网络应用开发一套完整的解决方案。uWSGI主要面向web及其标准服务,已经成功的应用于多种不一样的语言。因为uWSGI的可扩展架构,它可以被无限制的扩展用来支持更多的平台和语言。目前,你可使用C,C++和Objective-C来编写插件。项目名称中的“WSGI”是为了向同名的Python Web标准表示感谢,由于WSGI为该项目开发了第一个插件。uWSGI是一个Web服务器,它实现了WSGI协议、uwsgi、http等协议。uWSGI,既不用wsgi协议也不用FastCGI协议,而是自创了一个uwsgi的协议,uwsgi协议是一个uWSGI服务器自有的协议,它用于定义传输信息的类型(type of information),每个uwsgi packet前4byte为传输信息类型描述,它与WSGI相比是两样东西。听说该协议大约是fcgi协议的10倍那么快。

  1. uWSGI的主要特色以下:
  2. 超快的性能。
  3. 低内存占用(实测为apache2的mod_wsgi的一半左右)。
  4. 多app管理。
  5. 详尽的日志功能(能够用来分析app性能和瓶颈)。
  6. 高度可定制(内存大小限制,服务必定次数后重启等)。

其余拓展知识:Java Servlet、Sinatra、Rack

转载请注明:标点符 » 网关协议学习:CGI、FastCGI、WSGI

相关文章
相关标签/搜索