nginx_fast cgi_c++整理

本文详细介绍了Nginx作为高性能web server如何调用FastCGI程序以提高性能,包括Nginx与FastCGI接口的运作过程、安装与配置FastCGI进程管理器、FCGI接口方式启动动态脚本解析服务器等步骤。此外,文章还提供了fcgi_demo程序示例以及如何通过Nginx转发请求到FastCGI接口进行web发布。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.介绍

    Nginx - 高性能web server

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

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

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

​图1 Nginx+FastCGI运行过程​

    FastCGI接口方式在脚本解析服务器(CGI应用程序服务器)上启动一个或者多个守护进程对动态脚本进行解析,这些进程就是FastCGI进程管理器,或者称为FastCGI引擎。 spawn-fcgiPHP-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)执行选项

        -c </path/to/config> 为 Nginx 指定一个配置文件,来代替缺省的。不输入则使用默认的配置文件。

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

        -v 显示 nginx 的版本。

        -V 显示 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 文件中。

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

        命令 说明 备注

        TERM, INT 快速关闭  

        QUIT 从容关闭  

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

        USR1 重新打开日志文件  

        USR2 平滑升级可执行程序  

        WINCH 从容关闭工作进程  

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_emoweb发布

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;

}

    [编译]

    g++ demo.cc -o fcgi_demo  -lfcgi++ -lfcgi  

3.2.web发布

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

    2)启动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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值