1.介绍

高性能web server。

程序 - 常驻型CGI(Common Gateway Interface)程序,它是语言无关的、可伸缩架构的CGI开放扩展,其主要行为是将CGI解释器进程保持在内存中并因此获得较高的性能。

要调用FastCGI程序,需要用到FastCGI的进程管理器,Nginx本身没有集成类似的模块,我们可以使用lighttpd中的spawn-fastcgi。(也可安装nginx-fcgi来让nginx支持fast cgi)。

FastCGI接口在Linux下是socket(这个socket可以是文件socket,也可以是ip socket)。当Nginx将CGI请求发送给这个socket的时候,通过FastCGI接口,wrapper接收到请求,然后派生出一个新的线程,这个线程调用解释器或者外部程序处理脚本并读取返回数据;接着,wrapper再将返回的数据通过FastCGI接口,沿着固定的socket传递给Nginx;最后,Nginx将返回的数据发送给客户端。这就是Nginx+FastCGI的整个运作过程,如图1所示。

nginx不支持 put delete吗 nginx支持cgi_Nginx

图1 Nginx+FastCGI运行过程

接口方式在脚本解析服务器(CGI应用程序服务器)上启动一个或者多个守护进程对动态脚本进行解析,这些进程就是FastCGI进程管理器,或者称为FastCGI引擎。 spawn-fcgi与PHP-FPM都是FastCGI进程管理器(分别支持C/C++和PHP)。

 

2.准备工作

2.1.Nginx(这里我使用的是tengine)的安装、部署与配置

安装]     

./configure --prefix=${TENGINE_INSTALL_DIR} --with-openssl=${OPENSSL_SRC_DIR} --with-pcre=${PCRE_SRC_DIR} --group=www --user=www --with-http_stub_status_module --with-http_ssl_module

make

make install

[配置和管理]     

1)添加www用户组和用户www:

sudo /usr/sbin/groupadd -f www; sudo /usr/sbin/useradd -g www www

2)执行选项

为 Nginx 指定一个配置文件,来代替缺省的。不输入则使用默认的配置文件。

不运行,而仅仅测试配置文件。nginx 将检查配置文件的语法的正确性,并尝试打开配置文件中所引用到的文件。

显示 nginx 的版本。

显示 nginx 的版本,编译器版本和配置参数。

3)启动 - 默认和特殊

${TENGINE_INSTALL_DIR}/sbin/nginx (默认启动方式)

${TENGINE_INSTALL_DIR}/sbin/nginx -c ${TENGINE_INSTALL_DIR}/conf/nginx.conf (指定配置文件启动)

4)查看nginx进程号(master是主进程)

ps -ef | grep nginx 

5)重新加载配置文件

sudo kill -HUP [nginx主进程号]  或者 sudo nginx -s reload

6) 通过系统的信号控制 Nginx

可以使用信号系统来控制主进程。默认,nginx 将其主进程的 pid 写入到 ${TENGINE_INSTALL_DIR}/logs/nginx.pid 文件中。

主进程可以处理以下的信号:

命令 说明 备注

快速关闭  

从容关闭  

重载配置 用新的配置开始新的工作进程    从容关闭旧的工作进程

重新打开日志文件  

平滑升级可执行程序  

从容关闭工作进程  

7)默认目录结构

主目录:${TENGINE_INSTALL_DIR}/

配置目录:${TENGINE_INSTALL_DIR}/conf/

root目录:${TENGINE_INSTALL_DIR}/html/

可执行文件路径:${TENGINE_INSTALL_DIR}/sbin/

2.2.spawn_fastcgi的安装、部署与配置

地址https://github.com/lighttpd/spawn-fcgi 

./autogen.sh
./configure --prefix=${SPAWN_FCGI_INSTALL_DIR}
make
sudo cp -f ./src/spawn-fcgi ${TENGINE_INSTALL_DIR}/sbin/
2.3.fastcgi库的安装
地址 http://www.fastcgi.com/dist/fcgi.tar.gz
解压后,在/include/fcgio.h文件中加上 #include <cstdio>
./configure --prefix=${FCGI_INSTALL_DIR}
make
make install
 
3.fcgi_emo和web发布
3.1.fcgi_demo程序
#include <stdlib.h>
#include <iostream>
#include "fcgio.h"
 
using namespace std;
 
// Maximum bytes
const unsigned long STDIN_MAX = 1000000;
 
/**
 * Note this is not thread safe due to the static allocation of the
 * content_buffer.
 */
string get_request_content(const FCGX_Request& request)
{
    char* content_length_str = FCGX_GetParam("CONTENT_LENGTH", request.envp);
    unsigned long content_length = STDIN_MAX;
 
    if (content_length_str)
    {
        content_length = strtol(content_length_str, &content_length_str, 10);
        if (*content_length_str)
        {
            cerr << "Can't Parse 'CONTENT_LENGTH='"
            << FCGX_GetParam("CONTENT_LENGTH", request.envp)
            << "'. Consuming stdin up to " << STDIN_MAX << endl;
        }
 
        if (content_length > STDIN_MAX)
        {
            content_length = STDIN_MAX;
        }
    }
    else
    {
        // Do not read from stdin if CONTENT_LENGTH is missing
        content_length = 0;
    }
 
    char* content_buffer = new char[content_length];
    cin.read(content_buffer, content_length);
    content_length = cin.gcount();
 
    // Chew up any remaining stdin - this shouldn't be necessary
    // but is because mod_fastcgi doesn't handle it correctly.
 
    // ignore() doesn't set the eof bit in some versions of glibc++
    // so use gcount() instead of eof()...
    do cin.ignore(1024); while (cin.gcount() == 1024);
 
    string content(content_buffer, content_length);
    delete[] content_buffer;
    return content;
}
 
int main(void)
{
    // Backup the stdio streambufs
    streambuf* cin_streambuf = cin.rdbuf();
    streambuf* cout_streambuf = cout.rdbuf();
    streambuf* cerr_streambuf = cerr.rdbuf();
 
    FCGX_Request request;
 
    FCGX_Init();
    FCGX_InitRequest(&request, 0, 0);
 
    while (FCGX_Accept_r(&request) == 0)
    {
        fcgi_streambuf cin_fcgi_streambuf(request.in);
        fcgi_streambuf cout_fcgi_streambuf(request.out);
        fcgi_streambuf cerr_fcgi_streambuf(request.err);
 
        cin.rdbuf(&cin_fcgi_streambuf);
        cout.rdbuf(&cout_fcgi_streambuf);
        cerr.rdbuf(&cerr_fcgi_streambuf);
 
        const char* uri = FCGX_GetParam("REQUEST_URI", request.envp);
 
        string content = get_request_content(request);
 
        if (content.length() == 0)
        {
            content = ", World!";
        }
 
        cout << "Content-type: text/html\r\n"
        << "\r\n"
        << "<html>\n"
        << "  <head>\n"
        << "    <title>Hello, World!</title>\n"
        << "  </head>\n"
        << "  <body>\n"
        << "    <h1>Hello " << content << " from " << uri << " !</h1>\n"
        << "  </body>\n"
        << "</html>\n";
 
        // Note: the fcgi_streambuf destructor will auto flush
    }
 
    // restore stdio streambufs
    cin.rdbuf(cin_streambuf);
    cout.rdbuf(cout_streambuf);
    cerr.rdbuf(cerr_streambuf);
 
    return 0;
}

编译]

  

3.2.web发布

1)将CGI可执行程序fcgi_demo移动到nginx的安装目录下 ${TENGINE_INSTALL_DIR}/cgibin (文件夹不存在则自己创建) 

)启动spawn-fcgi管理进程,并绑定server IP和端口(不要跟nginx的监听端口重合)

${TENGINE_INSTALL_DIR}/sbin/spawn-fcgi -a 127.0.0.1 -p 8088 -F 10 ${TENGINE_INSTALL_DIR}/cgibin/fcgi_demo 

注意上面是一行。

查看选项含义:/spawn-fcgi -h】

查看一下8088端口是否已成功:netstat -na | grep 8088

3)更改nginx.conf配置文件,让nginx转发请求,注意先备份nginx.conf。

在http节点的子节点-"server节"点中下添加配置

rewrite /api1 /fcgi_demo.cgi break;
rewrite /api2 /fcgi_demo.cgi break;
location ~ \.cgi$ {
            fastcgi_pass 127.0.0.1:8088;
            fastcgi_index index.cgi;
            fastcgi_param SCRIPT_FILENAME fcgi$fastcgi_script_name;
            include fastcgi_params;
        }
}
 
可选配置:
fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx;
fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;
fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;
fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;
4)重启nginx或者重新加载配置文件
sudo ./nginx -s reload
5)打开浏览器访问一下吧
http://localhost/api1
或者:curl -d "chris" http://localhost/api1