FastCGI学习总结
FastCGI :Fast Common Gateway Interface(快速通用网关接口),它是CGI的增强版。FastCGI是一个快速、开放和安全的web server接口,解决了传统CGI的性能问题,却又没有带来编程的复杂性。老的CGI程序可以很轻易的移植成FastCGI程序。
FastCGI的技术原理如果想了解FastCGI的技术原理就要了解何为"短生存期应用程序",何为"长生存期应用程序"。
先从CGI技术开刀,以下是CGI技术的理论:每次当客户请求一个CGI的时候,Web服务器就请求操作系统生成一个新的CGI进程。当CGI满足要求后,服务器就杀死这个进程。服务器对客户端的每个请求都要重复这样的过程。
而FastCGI技术的理论为:FastCGI程序一旦产生后,他可以持续工作,足够满足客户的请求直到被明确的终止。如果你希望通过协同处理来提高程序的性能,你可以请求Web服务器运行多个FastCGI应用程序的副本。 CGI就是所谓的短生存期应用程序,FastCGI就是所谓的长生存期应用程序。
由于FastCGI程序并不需要不断的产生新进程,可以大大降低服务器的压力。并且产生较高的应用效率。
FastCGI的特点1.??????打破传统页面处理技术
传统的页面处理技术,程序必须与Web服务器或Application服务器处于同一台服务器中。这种历史已经早N年被FastCGI技术所打破,FastCGI技术的应用程序可以被安装在服务器群中的任何一台服务器,而通过TCP/IP协议与Web服务器通讯,这样做既适合开发大型分布式Web群,也适合高效数据库控制。
?
2.??????明确的请求模式
CGI技术没有一个明确的角色,在FastCGI程序中,程序被赋予明确的角色(响应器角色(Responder)、认证器角色(Authorizer)、过滤器角色(Filter))。
?
3.??????独立性
架构独立性:FastCGI接口并不绑定特定的应用服务器架构,应用既可以是单线程的也可是多线程的。
进程独立性:FastCGI进程是独立于服务器的进程,对FastCGI进程的调试不影响服务器。同理,FastCGI进程的崩溃也不至于服务器崩溃。
语言独立性:FastCGI技术目前支持语言有:C/C++、Java、Perl、Tcl、Python、SmallTalk、Ruby等。
先来看看传统CGI是怎么做的,如下图:
图一:CGI的数据流
CGI应用是通过标准的POSIX流(stdin, stdout, stderr和环境变量)加上环境变量,来与HTTP服务器进行通信。
?
与CGI类似,FastCGI采用的方法是:在HTTP进程和FastCGI进程之间创建一个全双工的连接,数据报通过FastCGI协议封装在两个进程之间传递。
stdin和环境变量被封装在连接的输入部分;stdout和stderr被封装在连接的输出部分。
因此,作为输入端,FastCGI程序从连接上接收数据,解包,分离出stdin和环境变量,然后调用应用处理逻辑。作为输出端,FastCGI用FastCGI协议打包stdout和stderr,发送给HTTP服务器处理。
?
由于FastCGI应用不要求和HTTP服务器运行在同一个节点上,因此,FastCGI支持两种形式的连接:1)流管道,用于在同一个节点上的通信;2)TCP流,用于不同节点上的通信。
下图是FastCGI应用和HTTP服务器不在同一个机器上的数据流图:图二:FastCGI和HTTP不在同一节点的数据流
程序框架不同于CGI程序的单次执行特性,FastCGI的主程序框架有一个循环,如下:
?
初始化部分,只执行一次,所以常常把一些耗时的工作放在此处理,如:打开和连接数据库,计算表和位图值等。
另外初始化部分,还完成环境变量初始化等工作。
?
然后,程序阻塞在FCGI_Accep()调用上,一旦有连接上了就处理,否则就阻塞。
#include <stdlib.h>
?
int count;
?
void initialize(void)
{
? count=0;
}
?
void main(void)
{
/* Initialization. */?
??initialize();
?
/* Response loop. */
? while (FCGI_Accept() >= 0)?? {
??? printf("Content-type: text/html\r\n"
?????????? "\r\n"
?????????? "<title>FastCGI Hello! (C, fcgi_stdio library)</title>"
?????????? "<h1>FastCGI Hello! (C, fcgi_stdio library)</h1>"
?????????? "Request number %d running on host <i>%s</i>\n",
??????????? ++count, getenv("SERVER_HOSTNAME"));
? }
}
<!--[if gte mso 9]><xml> <o:OLEObject Type="Embed" ProgID="Package" ShapeID="_x0000_i1027" DrawAspect="Content" ObjectID="_1332338208"> </o:OLEObject></xml><![endif]--><!--[if gte vml 1]><v:shape id="_x0000_i1028" type="#_x0000_t75" style='width:57pt;height:36.75pt' o:ole=""> <v:imagedata src="file:///C:\DOCUME~1\andylin\LOCALS~1\Temp\msohtml1\01\clip_image005.wmz" o:title="" /></v:shape><![endif]--><!--[if gte mso 9]><xml> <o:OLEObject Type="Embed" ProgID="Package" ShapeID="_x0000_i1028" DrawAspect="Content" ObjectID="_1332338209"> </o:OLEObject></xml><![endif]-->
环境变量
说明
ALL_HTTP
未包括在本表格中给出的变量内的所有HTTP标题,如:这个变量来自表格HTTP_<标题栏名称>
QUERY_STRING
传递给程式的 query 信息,即:在指向URL中跟在问号(?)后的信息
REMOTE_HOST
使用者发出 request 的远端 host 名称
REMOTE_ADDR
使用者发出 request 的远端 IP 位址
AUTH_TYPE
用来确定使用者合法性的监定方法
REMOTE_USER
使用者的合法名称
REMOTE_IDENT
发出 request 的使用者
CONTENT_TYPE
query 信息中的 MIME 类型
CONTENT_LENGTH
以字节为单位的从客户端接收来的脚步长度
HTTP_FORM
使用者发出 request 的电子邮件讯息
HTTP_ACCEPT
client 可以接受的 MIME 类型列表
HTTP_COOKIE
与你站点打交道的客户的任何cookie(存储片)集合
HTTP_USER_AGENT
client 用来发出 request 的浏览器
GATEWAY_INTERFACE
Server 使用的 CGI 版本
SERVER_NAME
Server 的 host 名称或 IP 位址
SERVER_SOFTWARE
回应 client request 的 Server 软体名称和版本
SERVER_PROTOCOL
传递资讯所用的协定名称或版本
SERVER_PORT
Server 正在执行的 port number
SERVER_PORT_SECURE
值为0或1,值1表示请求出现在加密端口
URL
请求的URL地址
REQUEST_METHOD
发出 request 的方法
PATH_INFO
传递给 CGI 程式的额外路径
PATH_TRANSLATED
存在 PATH_INFO 中的给定路径的传递版本
SCRIPT_NAME
程式执行时的 virtual path
DOCUMENT_ROOT
网路提供的文件服务所在路径
HTTP_REFERER
在读取 CGI 程式前,client 所指的文件 URL
?