#一、简述 Nginx支持使用FastCGI。它与CGI的区别在于,不需要重复启动CGI进程,从而节省了创建进程和结束进程的开销,避免了不必要的开销,提高了效率。

具体关于CGI和FastCGI的原理和运行流程请请参考这篇文章。

#二、开发环境 | 名称 | 版本 | |:------------: | :---------------------------------: | | 操作系统 | Ubuntu Server 12.04 64bit | | Nginx | 1.2.9 | | spawn-fcgi | 1.6.4 | | libfcgi | 最新版 |

其中spawn-fcgi是FastCGI的管理程序,负责启动FastCGI并创建和Nginx的连接。libfcgi是方便FastCGI开发的工具包。

接下來的操作都一样,解压源代码,./configure,make,make install,注意install的时候要有root权限。貌似libfcgi的源代码网站关闭了,所以建议使用二进制方法安装。在Ubuntu上直接apt-get:

sudo apt-get update
sudo apt-get install libfcgi-dev

#三、一个简单的例子:Hello World! ##1、功能 下面通过一个简单的FastCGI的实例来介绍开发过程,这个FastCGI接收用户的请求,然后向用户返回Hello World! 和用户请求的次数,以及请求中带有的参数。

##2、代码结构 FastCGI的代码结构应该是:对所需的资源进行初始化,然后在一个循环里不停的使用FCGI_Accept()等待请求,然后处理请求,输出响应。FastCGI比CGI高效的地方就体现在这里,用伪代码表示如下:

#include <fcgi_stdio.h>

int main() {
    初始化操作
    while(FCGI_Accept() >= 0) {
        处理请求
        输出响应   
    }

    return 0;
}

FCGI_Accept()从HTTP服务器接收一个请求,并且为请求创建一个与CGI兼容的运行环境(execution environment)。

如果程序当做CGI被调用,则第一次调研FCGI_Accept()函数是一个空操作(no-op),再次调用则会返回-1。这样做就可以使得正确编码的FastCGI程序(即按照上面结构来编码)只处理一个请求然后退出,表现的就像CGI程序一样。

如果程序当错FastCGI被调用,则首次调用FCGI_Accept()函数表示程序已经完成了初始化操作并准备好接收第一个请求了。接下来再调用FCGI_Accept()表示程序已经处理完了当前的请求并准备好接收一个新的请求。程序可以调用FCGI_Finish()来表示处理完了当前的请求,但是不接受新的请求。一段时间后,程序准备好再次接收新的请求时,可以再调用FCGI_Accept()

有关FCGI_Accept()和FCGI_Finish()的具体用法请参考Man Page: FCGI_Accept(), FCGI_Finish()。 中文翻译: FCGI_Accept(), FCGI_Finish()。

##3、获取请求中的参数 FastCGI通过环境变量来传递请求的相关数据,具体内容如下表(内容来自CGI101):

环境变数

说明

DOCUMENT_ROOT

The root directory of your server

HTTP_COOKIE

The visitor's cookie, if one is set

HTTP_HOST

The hostname of the page being attempted

HTTP_REFERER

The URL of the page that called your program

HTTP_USER_AGENT

The browser type of the visitor

HTTPS

"on" if the program is being called through a secure server

PATH

The system path your server is running under

QUERY_STRING

The query string

REMOTE_ADDR

The IP address of the visitor

REMOTE_HOST

The hostname of the visitor

REMOTE_PORT

The port the visitor is connected to on the web server

REMOTE_USER

The visitor's username (for .htaccess-protected pages)

REQUEST_METHOD

GET or POST

REQUEST_URI

The interpreted pathname of the requested document or CGI (relative to the document root)

SCRIPT_FILENAME

The full pathname of the current CGI

SCRIPT_NAME

The interpreted pathname of the current CGI (relative to the document root)

SERVER_ADMIN

The email address for your server's webmaster

SERVER_NAME

Your server's fully qualified domain name (e.g. www.cgi101.com)

SERVER_PORT

The port number your server is listening on

SERVER_SOFTWARE

The server software you're using (e.g. Apache 1.3)

##4、代码

#include <fcgi_stdio.h>
#include <stdlib.h>

int main() {
    unsigned int req_count = 0;

    while(FCGI_Accept() >= 0) {
        FCGI_printf("Content-type: text/html\r\n\r\n");
        FCGI_printf("<title>Hello World!</title>"
            "<h1>Hello World!</h1>");
        FCGI_printf("<h2>request times: %u</h2>", ++req_count);
        FCGI_printf("QUERY_STRING: %s</br>", getenv("QUERY_STRING"));
        FCGI_printf("REMOTE_ADDR: %s</br>", getenv("REMOTE_ADDR"));
    }   

    return 0;
}

注意一点,输出内容必须带有\r\n把响应的头部和正文分开,响应的头部可以为空,但是\r\n不可以省略。否则Nginx会出现Error页面。

nginx的fastcgi进程响应慢的原因是什么_操作系统

##5、编译 编译时记得添加-lfcgi选项表示要链接libfcgi库。

$ g++ -W hello_fcgi.cpp -o hello_fcgi -lfcgi

#四、使用FastCGI ##1、修改Nginx配置文件 首先需要修改一下Nginx的配置文件nginx.conf,指定使用FastCGI的地方。比如我们想让所有访问/fcgi这个路径的请求都交给hello_fcgi程序处理,那么就在server块中添加如下内容:

location /fcgi {
    fastcgi_pass 127.0.0.1:8000; 
    fastcgi_index index.cgi;
    include fastcgi.conf;
}

这段内容告诉Nginx处理访问/fcgi路径的请求的规则,以及FastCGI管理器的IP和端口号和一些其他配置,Nginx收到请求后会把请求转发给这个地址,然后会重定向到FastCGI程序。 通知Nginx重新读取配置文件:

$ sudo /usr/local/nginx/sbin/nginx -s reload

##2、使用FastCGI管理器启动FastCGI程序 现在使用之前安装的spawn-fcgi来启动刚才编写的FastCGI程序:

$ spawn-fcgi -p 8081 -f ./hello_fcgi

其中-p选项指定绑定的端口号,还可以使用-a选项指定绑定的ip地址,注意这里的IP和端口号要和nginx.conf中配置的匹配。-f选项指定FastCGI程序的位置。spawn-fcgi的更多用法可以使用-h参数来查看。正常情况下成功启动后spawn-fcgi会提示如下信息:

spawn-fcgi: child spawned successfully: PID: 52825

##3、效果 现在可以使用浏览器访问Nginx服务器的/fcgi路径查看效果了:

nginx的fastcgi进程响应慢的原因是什么_操作系统_02