原文地址:http://www.fastcgi.com/devkit/doc/fastcgi-whitepaper/fastcgi.htm
随着web的广泛应用,对动态内容的需求也越来越迫切。CGI提供了一种解决方案,但是CGI有一个最大的问题就是无法满足高密度请求环境下的性能需求。Open Market为了解决这个问题从而开发了FastCGI。
FastCGI是一个快速,开源,安全的web服务器接口,它是兼容CGI的API,但是它解决了CGI中性能问题,
CGI是一个标准的web服务器应用程序接口,它第一次是在NCSA服务器中实现,它具有一下特点:
CGI也有很多缺陷,其中最大的缺陷是性能问题:针对每一个请求,创建一个新的进程。当请求结束就终止进程。在高密度请求的环境下,这种反复性创建进程使得的整体性能很差。
CGI有另外一个缺点:CGI只扮演简单的“回应”角色,它针对每一个请求,生成一个回应,返回给客户端。CGI程序无法和Web服务器其他层次进行“通信”,比如不支持认证,日志等功能。
为了解决CGI程序的性能问题,服务器厂商针对每一个服务器开发出相应的服务端API,通过该API可以实现与CGI相似的功能。最出名的有NSAPI(Netscape)和ISAPI(Microsoft)。Apache环境下有也相应的服务端API。通过服务端API,应用程序直接和web服务器进行交互,它的性能明显快于CGI应用程序。该应用程序直接运行在服务器端,并且永久存在,不需要像CGI那样反复创建进程。另外web服务器APIs提供更加多的功能,比如权限控制,能够操纵服务器日志文件,可以在多个层次处理服务器各种类型的请求。
尽管服务端API有以上优点,但是它也有以下缺点:
FastCGI结合上面CGI和服务器APIs的优点,它和CGI一样,FastCGI应用程序运行在分开的独立的进程。它还有以下的优点:
下面的内容将会详细介绍FastCGI的接口,协议,开发类库。
FastCGI提供了和CGI类似的功能,为了更好的理解FastCGI,我们首先必须弄到CGI接口,基本的CGI请求处理流程如下:
FastCGI和CGI比较相似,但是有下面两点不同:
单线程结构下的FastCGI进程处理请求的过程如下:
FastCGI程序可以运行在本地或者远程,运行本地时,服务器通过全双工管道来连接FastCGI应用程序。对于远程,服务器使用TCP连接。FastCGI程序可以是单线程或多线程,对于单线程程序,web服务器创建一个FastCGI进程池来处理客户端请求。该进程池的大小是可以配置的。对于多线程FastCGI程序可以同时接受多个web服务器请求来同时处理该请求。
现实中有这样一个挑战:如果应用程序运行在外部web服务器上,但是它需要内部数据库上数据或者应用。下图显示一个典型的架构,外部服务器在防火墙的管理下限制操作内部服务器的数据和应用程序:
如果使用CGI和服务端APIs,而应用程序运行在web服务器。此时意味着服务器管理员必须复制所需的数据库信息在系统上托管的Web服务器(而这在要求不影响防火墙的安全性的前提下,是很难做到自动化的管理)。或者,管理员可以建立一座“桥梁”,允许通过Web服务器访问内部数据库和应用程序(这实际上是重新发明了远程FastCGI)。
通过简单配置远程FastCGI,应用程序可以运行在内部服务器上,当使用适当的防火墙配置和审计,这种方法提供了一个安全,高性能,可伸缩的方式,使内部到外部网络的应用程序和数据。
对于资源密集性的CGI和服务的API程序,web服务器很快就成为整体吞吐量的瓶颈。最常见解决这个问题的办法是购买一个更大更快的web服务器或者把web网站分布到多个服务器上(需要改变原先的链接)。
管理员可以通过配置远程FastCGI,对于那些资源密集性的应用程序可以移出主web服务器,并且通过该办法不需要改变原先内容的连接地址,管理员可以通过多个低廉的服务器来运行FastCGI应用程序。
对于远程FastCGI程序来说,有两个安全问题:认证和资料保密。FastCGI必须只接受来自信任的的服务器连接(API中提供了对支持IP的验证功能)。并且未来版本将会提供SSL和PCT安全链接来保证数据传输的安全。
本节主要介绍一下web服务器和FastCGI应用程序之间的连接的通信协议。大部分应用程序开发人员其实不需要知道通信协议仅仅通过使用FastCGI API来完成程序开发。
FastCGI通信协议使用一个简单的封包记录格式:
其中Protocol Version指定当前协议的版本。Record Type指定该记录的类型(详细见下面表格)
FCGI_PARAMS | 传送名称/值组合的资料,如环境变数 |
---|---|
FCGI_STDIN | 传送标准输入资料(从伺服器到应用程式) |
FCGI_DATA | 传送过滤资料到应用程式 |
FCGI_STDOUT | 传送标准输出资料(从应用程式到伺服器) |
FCGI_STDERR | 传送标准错误资料(从应用程式到伺服器) |
FCGI_END_REQUEST | 结束(应用程式及伺服器皆可用) |
介绍的有点简单吗!!!后面去详细看看,红色标记一下
对于CGI程序来说,它其中一个缺陷就是它仅仅提供Responder回应者的功能。而FastCGI提供了一个功能扩展包括下面三个不同应用功能:
在未来的版本将会提供其他的功能,比如日志功能。下面只是简单介绍,后面去分别写写相应功能的程序,红色标记一下
Open Market开发一套FastCGI API实现了FastCGI协议,该库使得FastCGI开发人员可以和CGI程序一样,轻松书写FastCGI程序。
应用程序库提供了一个替代方案来替代基于C语言标准的IO运行时类库,比如printf()和gets()。该类库把标准的输入,输出,错误输出转换到FastCGI通信协议,对于其他的请求由操作系统的标准IO进行处理。
使用FastCGI应用程序库有以下几个好处:
下面是一个简单的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); }
fcgi_stdio.h头文件提供一个C IO标准运行库的FastCGI替代运行时。函数FCGI_Accept()接受一个新的来自web服务器的请求。
在设计FastCGI应用程序库时,追求更易的CGI移植。很多应用程序可以通过添加简单的循环,并重新编译从而把CGI转化为FastCGI应用程序。每一个FastCGI包含一个初始段和一个请求循环段:
Initialize application; while(FCGI_Accept() >= 0) { Process request; }
在转换以后,程序员需要优化FastCGI程序来寻求最优的性能:
FastCGI程序有多快?该问题主要依赖应用程序。本节讨论一个现实问题的处理的性能,并且给出一个FastCGI应用程序加速方案。
Static file
|
21ms + 0.19ms per Kbyte
|
FastCGI
|
22ms + 0.28ms per Kbyte
|
CGI
|
59ms + 0.37ms per Kbyte
|
CGI | 59ms + 50ms + (0.37ms)(5) = 111ms |
FastCGI | 22ms + (0.28ms)(5) = 23ms |