FastCGI: A High-Performance Web Server Interface 中文翻译版本

来源:互联网 发布:linux文件系统管理 编辑:程序博客网 时间:2024/06/05 11:53

         原文地址:http://www.fastcgi.com/devkit/doc/fastcgi-whitepaper/fastcgi.htm


         这篇文章是FastCgi的白皮书,在前言部分介绍CGI和服务器接口的优缺点,算是CGI/FastCGI中比较好的文章。所以就转过来。目的不是为了翻译,而是为了以后看起来比较清晰一点,http://home.educities.edu.tw/shirock/comp/fastcgi.htm这个地址里面有繁体中文版,有所参考该文章。勉强给这篇文章加上翻译的类别吧!嘿嘿

一 前言

         随着web的广泛应用,对动态内容的需求也越来越迫切。CGI提供了一种解决方案,但是CGI有一个最大的问题就是无法满足高密度请求环境下的性能需求。Open Market为了解决这个问题从而开发了FastCGI。

         FastCGI是一个快速,开源,安全的web服务器接口,它是兼容CGI的API,但是它解决了CGI中性能问题,

CGI(Common Gateway Interface)

         CGI是一个标准的web服务器应用程序接口,它第一次是在NCSA服务器中实现,它具有一下特点:

  • 简单:和编程语言无关:CGI应用程序可以利用任意编程语言进行开发,C,JAVA,Perl
  • 独立进程:CGI的解析是进程独立的。每一个请求开始通过创建一个进程,处理完以后,进程就结束。如果进程出现bug,不会影响web服务器的运行
  • 开放性标准:在每一个web服务器都实现了CGI。
  • 体系结构独立:CGI和特定的服务器体系结构无关(单线程,多线程都无所谓)

         CGI也有很多缺陷,其中最大的缺陷是性能问题:针对每一个请求,创建一个新的进程。当请求结束就终止进程。在高密度请求的环境下,这种反复性创建进程使得的整体性能很差。

         CGI有另外一个缺点:CGI只扮演简单的“回应”角色,它针对每一个请求,生成一个回应,返回给客户端。CGI程序无法和Web服务器其他层次进行“通信”,比如不支持认证,日志等功能。

服务端APIs

         为了解决CGI程序的性能问题,服务器厂商针对每一个服务器开发出相应的服务端API,通过该API可以实现与CGI相似的功能。最出名的有NSAPI(Netscape)和ISAPI(Microsoft)。Apache环境下有也相应的服务端API。通过服务端API,应用程序直接和web服务器进行交互,它的性能明显快于CGI应用程序。该应用程序直接运行在服务器端,并且永久存在,不需要像CGI那样反复创建进程。另外web服务器APIs提供更加多的功能,比如权限控制,能够操纵服务器日志文件,可以在多个层次处理服务器各种类型的请求。

         尽管服务端API有以上优点,但是它也有以下缺点:

  • 复杂性:服务端APIs有一个很高学习台阶,增加实现和修改的代价。
  • 编程语言不独立:应用程序必须针对特定服务端APIs采用特定适应的编程语言。
  • 进程不独立:因为服务器进程是运行在web服务器的进程空间,应用程序和服务器之间关联太强,任何一端有bug,都会导致另外一端奔亏。
  • 特定服务器依赖性:开发出来的应用程序过度依赖服务器软件和版本。
  • 和服务器体系结构相绑定:应用程序和服务器共用体系结构:如果服务器是多线程,那么应用程序必须考虑线程安全性。如果服务器是单线程的,那么多线程的应用程序无法得到性能上得到提高,如果服务器改变其体系结构,那么以前开发的应用程序也需要进行改变。

 FastCGI

         FastCGI结合上面CGI和服务器APIs的优点,它和CGI一样,FastCGI应用程序运行在分开的独立的进程。它还有以下的优点:

  • 性能:FastCGI进程是持久的,它可以重复利用来处理多次web请求。这一点解决了CGI重新的创建和注销进程而带来性能问题。
  • 和CGI之间的移植和兼容功能:利FastCGI API可以很轻易的把已经存在的CGI程序移植过来。并且利用FastCGI API开发出现的应用程序可以当着CGI程序进行运行,并且兼容老的服务器。
  • 语言独立:和CGI程序一样,FastCGI应用程序可以利用任意编程语言进行编写。
  • 进程独立:FastCGI应用程序和服务器之间是进程独立的,应用程序的奔亏不会影响服务器的正常运行。并且应用程序不可以从web服务器中得到任何安全相关的信息,比如session keys
  • 和特定服务器无关:FastCGI支持大部分的服务器,包括Apache,lighttpd等。
  • 体系结构独立:FastCGI应用程序和特定服务器体系结构独立。
  • 支持分布式运行:fastCGI支持远程运行应用程序,在分布式负载均衡和管理中,该功能比较实用。

         下面的内容将会详细介绍FastCGI的接口,协议,开发类库。

二 FastCgi接口

         FastCGI提供了和CGI类似的功能,为了更好的理解FastCGI,我们首先必须弄到CGI接口,基本的CGI请求处理流程如下:

  1. 对于每请求,web服务器创建一个新的进程,并且进程进行自我初始化。
  2. web服务器通过环境变量向CGI程序传递请求信息(包括远程请求主机信息,HTTP头部等信息)
  3. web服务器通过标准的IO输入向CGI程序传递客户端输入(比如用户相关的HTML的表达等信息)
  4. CGI程序通过标准IO输出向客户端写返回信息,web服务器通过标准错误输出进行输出错误信息。
  5. CGI进程退出,请求完成。

         FastCGI和CGI比较相似,但是有下面两点不同:

  • FastCGI进程是持久的。每一个进程,处理完请求以后,将会等待下一个请求,而不是结束该进程。
  • CGI是通过操作系统的环境变量和pipes管道进行数据的传输,而FastCGI通过单一的全双工连接来复用系统环境变量,标准/错误输入输出。因此FastCGI程序可以通过TCP连接来实现web服务器和FastCGI程序之间的通信,从而使其可以运行在远程机器上。

         单线程结构下的FastCGI进程处理请求的过程如下:

  1. web服务器启动时候,创建一个FastCGI进程池来处理后续的所有请求,该进程池中保护多个进程,该进程可以在启动时候创建,也可以通过命令的方式进行创建。
  2. FastCGI完成自己初始化,并等待从web服务器来的新的连接请求
  3. 当来了一个客户端请求,web服务器和FastCGI之间创建一个连接,web服务器通过该连接向FastCGi程序发生CGI环境变量和标准的输入。
  4. FastCGI进程处理完请求,把标准的输出信息和错误信息通过相同的连接发送到web服务器
  5. FastCGI关闭该连接,请求结束,进程继续等待后续的连接接

         FastCGI程序可以运行在本地或者远程,运行本地时,服务器通过全双工管道来连接FastCGI应用程序。对于远程,服务器使用TCP连接。FastCGI程序可以是单线程或多线程,对于单线程程序,web服务器创建一个FastCGI进程池来处理客户端请求。该进程池的大小是可以配置的。对于多线程FastCGI程序可以同时接受多个web服务器请求来同时处理该请求。

远程FastCGI

         FastCGI远程运行能力提供了很多主要的好处,本文下面部分主要来谈论一下FastCGI的远程运行功能和相应的安全问题。

利用FastCGI来适应防火墙的设置

         现实中有这样一个挑战:如果应用程序运行在外部web服务器上,但是它需要内部数据库上数据或者应用。下图显示一个典型的架构,外部服务器在防火墙的管理下限制操作内部服务器的数据和应用程序:

error-file:TidyOut.log

         如果使用CGI和服务端APIs,而应用程序运行在web服务器。此时意味着服务器管理员必须复制所需的数据库信息在系统上托管的Web服务器(而这在要求不影响防火墙的安全性的前提下,是很难做到自动化的管理)。或者,管理员可以建立一座“桥梁”,允许通过Web服务器访问内部数据库和应用程序(这实际上是重新发明了远程FastCGI)。

         通过简单配置远程FastCGI,应用程序可以运行在内部服务器上,当使用适当的防火墙配置和审计,这种方法提供了一个安全,高性能,可伸缩的方式,使内部到外部网络的应用程序和数据。

通过远程FastCGI来实现负载均衡

         对于资源密集性的CGI和服务的API程序,web服务器很快就成为整体吞吐量的瓶颈。最常见解决这个问题的办法是购买一个更大更快的web服务器或者把web网站分布到多个服务器上(需要改变原先的链接)。

         管理员可以通过配置远程FastCGI,对于那些资源密集性的应用程序可以移出主web服务器,并且通过该办法不需要改变原先内容的连接地址,管理员可以通过多个低廉的服务器来运行FastCGI应用程序。

远程FastCGI相关安全问题

         对于远程FastCGI程序来说,有两个安全问题:认证和资料保密。FastCGI必须只接受来自信任的的服务器连接(API中提供了对支持IP的验证功能)。并且未来版本将会提供SSL和PCT安全链接来保证数据传输的安全。

FastCGI协议

         本节主要介绍一下web服务器和FastCGI应用程序之间的连接的通信协议。大部分应用程序开发人员其实不需要知道通信协议仅仅通过使用FastCGI API来完成程序开发。

FastCGI通信协议使用一个简单的封包记录格式:

error-file:TidyOut.log

         其中Protocol Version指定当前协议的版本。Record Type指定该记录的类型(详细见下面表格)

FCGI_PARAMS传送名称/值组合的资料,如环境变数FCGI_STDIN传送标准输入资料(从伺服器到应用程式)FCGI_DATA传送过滤资料到应用程式FCGI_STDOUT传送标准输出资料(从应用程式到伺服器)FCGI_STDERR传送标准错误资料(从应用程式到伺服器)FCGI_END_REQUEST结束(应用程式及伺服器皆可用)

         介绍的有点简单吗!!!后面去详细看看,红色标记一下

三 FastCgi应用功能

         对于CGI程序来说,它其中一个缺陷就是它仅仅提供Responder回应者的功能。而FastCGI提供了一个功能扩展包括下面三个不同应用功能:

  1. Responder回应者:这个是FastCGI最基本的功能,和CGI兼容。
  2. Filter过滤器:FastCGI应用程序可以在把内容送回给client之前进行过滤处理。
  3. Authorizer认证:FastCGI提供一个对应用请求的权限控制。

         在未来的版本将会提供其他的功能,比如日志功能。下面只是简单介绍,后面去分别写写相应功能的程序,红色标记一下

回应者

         FastCGI的回应者角色和CGI的功能相同。当一个请求被处理以后,FastCGI应用程序生成一个反应返回给客户端。一般都是HTML页面。

过滤器

         过滤器角色允许FastCGI应用程序在web server把数据返回给客户端之前进行过滤处理。
         假设web服务器被配置使得可以自动把所有的.sgml的扩展文件在返回给客户端之前转化为.html文件。下面图显示该处理过程:
error-file:TidyOut.log
         过滤器可以通过缓存过滤以后的结果从而提高系统的性能。并且服务器在请求中提供了修改时间,从而应该程序可以更加修改时间来更新缓存。
         其中过滤器主要的功能有:
  1. 未知格式的转换
  2. 动态内容(比如文档中包含嵌入SQL语句,或者动态插入广告)
  3. 提供一个标准模板:头部,背部,和背景

认证

         认证允许FastCGI应用程序来控制每一个请求的权限控制。如果认证角色返回“200 OK”,那么web服务器就可以把结果返回给客户端,如果认证器返回其他的结果,那么该结果被返回给客户端,并且该请求也因此而结束。该回应可以是任意合法的HTTP返回,包括“Access Denied”或者“Redirect”。
         认证主要应用在:
  1. 通过用户名和密码来进行权限控制
  2. 复杂的访问策略,比如基于时间的访问控制
  3. 智能卡认证领域
  4. 动态重定向,根据认证配置文件来动态重定向用户的请求

四 FastCGI应用程序库

         Open Market开发一套FastCGI API实现了FastCGI协议,该库使得FastCGI开发人员可以和CGI程序一样,轻松书写FastCGI程序。

         应用程序库提供了一个替代方案来替代基于C语言标准的IO运行时类库,比如printf()和gets()。该类库把标准的输入,输出,错误输出转换到FastCGI通信协议,对于其他的请求由操作系统的标准IO进行处理。

         使用FastCGI应用程序库有以下几个好处:

  1. 开发人员不需要学习新的API来开发FastCGI应用程序。
  2. 已经存在的CGI应用程序可以很容易移植到FastCGI中
  3. 看到什么perl。不关心,不翻译了。

         下面是一个简单的FastCGI程序:

#include <fcgi_stdio.h>    void main(void)    {        int count = 0;        while(FCGI_Accept() >= 0) {            printf("Content-type: text/html\r\n");            printf("\r\n");            printf("Hello world!<br>\r\n");            printf("Request number %d.", count++);        }        exit(0);    }

         该程序返回一个"Hello Word"给客户端,并且包含一个该FastCGI处理的计数器,并且显示在每一次的请求返回结果里面。

         fcgi_stdio.h头文件提供一个C IO标准运行库的FastCGI替代运行时。函数FCGI_Accept()接受一个新的来自web服务器的请求。

CGI程序移植

         在设计FastCGI应用程序库时,追求更易的CGI移植。很多应用程序可以通过添加简单的循环,并重新编译从而把CGI转化为FastCGI应用程序。每一个FastCGI包含一个初始段和一个请求循环段:

Initialize application;while(FCGI_Accept() >= 0) {Process request;}

         为了更加容易移植,利用FastCGI库开发的程序可以根据它被调用的方式,来确定其是以CGI或者FastCGI程序的类型来运行。类库可以检查执行环境,自动选择FastCGI或者标准的IO进行运行。

         在转换以后,程序员需要优化FastCGI程序来寻求最优的性能:

  1. 修复资源泄漏问题。大部分CGI程序不需要管理内存或者关闭文件,因为请求结束,进程关闭以后,会自动进行相应的资源回收。在转化以后需要进行资源泄漏问题的修复。
  2. 修复由于状态保留的而导致的问题。每一个应用程序必须确保它的每一个请求的状态不会影响后面的请求。
  3. 功能组合。CGI应用程序建议把功能分散为很多个小的应用程序,一个功能一个进程,这样可以减少CGI程序加载时候的消耗。而在FastCGI程序中,建议把相应功能的程序放到同一个程序中,从而减少需要管理的进程的数目,和充分利用进程的共有资源。

五 FastCGI性能分析

         FastCGI程序有多快?该问题主要依赖应用程序。本节讨论一个现实问题的处理的性能,并且给出一个FastCGI应用程序加速方案。

FastCGI vs CGI

         本文在Open Market服务器上验证了各个方式的吞吐量。我们利用CGI,FastCGI,以及静态文件来生成一定的输出来评判三者性能。时间包括=客户端,服务端之间的连接时间以及i他相关时间+加上应用程序处理每一字节的时间。
Static file
21ms + 0.19ms per Kbyte
FastCGI
22ms + 0.28ms per Kbyte
CGI
59ms + 0.37ms per Kbyte
         通过上面的表格,我们知道,FastCGI的性能和静态文件相当,并且明显好于CGI。
         下面我们利用上面的数据来估算一下把CGI程序移植到FastCGI程序所带来的性能提升。假设CGI应用程序每次需要50ms来完成FastCGI程序的初始化阶段的执行过程,请求的性能计算如下:
CGI59ms + 50ms + (0.37ms)(5) = 111msFastCGI22ms + (0.28ms)(5) = 23ms         我们可以看到,由于FastCGI程序不需要每次初始化和创建进程,它可以在原先的基础上提高5倍的性能。

六 总结

         今天,我们需要一个快速,开发,可维护,简单,稳定,安全的平台,其中FastCGI的设计满足了这个要求,并且在CGI上提供一个逻辑上的扩展,这是的开发者可以很容易把以前的CGI程序移植到现在的平台。


原创粉丝点击