最新消息:

FastCGI

c admin 2880浏览 0评论

如今,Web内容多是动态生成的,通常是由Web服务器的调用脚本生成。有很多常用的服务端脚本,PHP,ASP,Perl,Python,不一而足。然而,很久以前,很流行的生成动态内容的方法就是CGI。CGI(Common Gateway Interface)是一种协议,它定义了WebServer与CGI程序的通信方式:WebServer接受客户端的HTTP请求,然后建立进程执行CGI程序,客户端的请求参数通过环境变量和标准输入的方式传递给CGI程序,CGI程序根据请求生成内容(查询数据库,读取文件等),然后通过标准输出的方式将结果传递给WebServer,由后者返回给客户端。
这种方式有很多优点:

  • 协议简洁,易于理解;
  • 与语言无关,可以使用任何语言来编写CGI程序;
  • 进程隔离,CGI程序的bug不会影响到WebServer的稳定性;

但是,这种方式也存在一定的缺陷/缺点:

  • 性能低下,对于客户端的每一次请求,都需要建立和销毁进程,因而并发度也受到极大限制;
  • 没有状态,同样由于每次请求都建立独立的进程,CGI程序很难在多次请求之间维持特定的状态。

FastCGI

于是,FastCGI,另一种类似的协议被提出了。顾名思义,该协议的提出就是要克服普通CGI程序性能低下的缺点,同时又具备普通CGI的所有优点。通信方式上,FastCGI与CGI大同小异,主要区别在于:

  • FastCGI程序通常以Daemon方式运行,只启动一次,接下来便可以持续地接受来自WebServer的请求;
  • FastCGI程序与WebServer以网络方式通信,FasCGI监听TCP服务端口或建立Unix Socket,WebServer将请求转发给FastCGI;
  • 由于采用网络方式通信,因而允许WebServer和FastCGI程序的分布式部署;

接口方面,有很多针对不同语言的FastCGI开发套件,保证了FastCGI与普通CGI具有很大的兼容性,普通CGI程序作极小的改动便可以以FastCGI的形式运行。

FastCGI C语言示例

先来看一个简单的普通CGI程序,他简单地向客户端打印”Hello, World”,

#include <stdio.h>
int
main(int argc, char **argv)
{
    fprintf(stdout, "Content-Type: text/plainnn");
    fprintf(stdout, "Hello, World");
    return 0;
}

下面是一个对应的FastCGI程序,

//~ hello.c
#include <fcgi_stdio.h>
int
main(int argc, char **argv)
{
    while (FCGI_Accept() >= 0) {
        fprintf(FCGI_stdout, "Content-Type: text/plainnn");
        fprintf(FCGI_stdout, "Hello, World");
    }
    return 0;
}

我们看到,两个程序在结构上是极其相似的,不同地是FastCGI程序的功能代码包含在了一个循环中,FCGI_Accep()用来接受请求。另外FastCGI的输出目的也变成了FCGI_stdout,这需要包含libfcgi的头文件fcgi_stdio.h。
为了演示这个FastCGI程序,这里使用Nginx作为WebServer。Nginx没有直接支持普通CGI,但却直接支持FastCGI。(事实上,Nginx对PHP的支持也是通过FastCGI来实现的)
首先,编译该程序,然后通过spawn-fcgi来启动,

$ cc hello.c -o hello -lfcgi
$ spawn-fcgi -a 127.0.0.1 -p 9000 -f ./hello -P /tmp/spawn-fcgi-hello.pid

  然后,编辑Nginx的配置文件(没有使用过Nginx的同学,可以自行查找相关资料),在server区块加入下面内容

location /hello {
    include fastcgi.conf;
    fastcgi_pass 127.0.0.1:9000;
}

reload或者重启Nginx,

$ curl http://localhost/hello
Hello, World

参考资料:
CGI RFC 3875
FastCGI

转载请注明:爱开源 » FastCGI

您必须 登录 才能发表评论!