必威体育Betway必威体育官网
当前位置:首页 > IT技术

Fastcgi

时间:2019-06-08 22:43:10来源:IT技术作者:seo实验室小编阅读:70次「手机版」
 

fastcgi

CGI

CGI是一个标准,它的英文Common Gateway Interface CGI , 所以从英文也可以看到它是C/S之间数据传输的一个标准。它主要用于浏览器向服务器发送一些参数,再由服务器上的程序进行运算然后返回结果的过程,在这个过程中CGI起着一个标准的作用,它规定了数据是如何交互的。有了CGI标准后,我们可以把写好的CGI程序放在任何一个符合CGI标准的Server上进行数据交互。

对于CGI标准来讲它要求我们必须通过0号文件描述符去读取,从1号文件描述符去写回数据。所以一般Server为了支持CGI标准都会做如下的操作:

  • Server每次遇到CGI请求的时候会fork一个子进程去execve这个CGI程序。Server收到的参数通过环境变量传递,在fork后会对子进程的0、1号文件描述符(标准输入、标准输出)进行重定向,一般重定向为父进程生成的相应IPC的文件描述符。然后execve CGI程序,替换成功后会等待子进程的运算结果,收到结果后再把它返回给浏览器。这种方式就是符合了CGI标准,我们写的CGI程序只要符合从标准输入读取数据,从标准输出输出数据即可。

    这里写图片描述

fastcgi

  相比于cgi(fork+exec)的方式,fastcgi一般由一个cgi管理器进程或者服务器(Apache)去fork一个相应的cgi进程,这个cgi进程一直阻塞等待cgi的请求,一般由代理服务器(nginx)将HTTP请求转发给fastcgi进程,fastcgi接收到代理服务器的Socket的请求后,通过Socket进行数据交互。

  这样缺点是浪费内核资源,优点是效率高,不用每次再次去fork+execve了。

这里写图片描述这里写图片描述

这里写图片描述

实战

我们实战环境

  1. Fastcgi c++库
  2. nginx
  3. spawn-cgi (fastcgi 管理器)

spawn-fcgi

Nginx不能像Apache那样直接执行外部可执行程序,但是Nginx可以作为代理Server,将请求转发给后端FastCGI进程,FastCGI进程进行运算,然后把结果返回给Nginx,Nginx再把相应的内容返回给浏览器。

spawn-fcgi使用pre-fork模型,主要功能是打开监听端口,绑定地址,然后fork-and-exec创建FastCGI应用程序进程,创建完所有FastCGI进程后自动退出。FastCGI进程会进行初始化,然后进入死循环侦听socket的链接请求。

参数 含义
-f FastCGI程序的位置
-p 生成的FastCGI程序绑定什么port
-s 绑定的unix domain socket
-C 产生的PHP进程数默认5(c++写的无视)
-F fork多少个FastCGI进程(C/C++)
-P 指定进程的默认路径(在Linux进程的默认路径也属于进程数据被记录在PCB中)
-u/-g 指定 euid / egid

FastCGI c++ demo

echo demo
#include "fcgi_config.h"
#include <stdlib.h>
#include <unistd.h>
#include "fcgi_stdio.h"

static void printEnv(char *label,char **envp)
{
    printf("%s:<br>\n<pre>\n",label);
    for(;*envp != NULL;envp++){
        printf("%s\n",*envp);
    }
    printf("</pre><p>");
}

int main()
{
    char **initialEnv = environ;
    int count = 0;
    while(FCGI_Accept()>=0){
        char *contentLength = getenv("CONTENT_LENGTH");
        int len;
    }
    printf("Content-type: text/html\r\n"
            "\r\n"
            "<title>FastCGI echo</title>"
            "<h1>FastCGI echo</h1>\n"
            "Request number %d,  Process ID: %d<p>\n", ++count, getpid());
    if(contentLength != NULL){
        len = strtol(contentLength,NULL,10);
    }else{
        len = 0;
    }
    if(len <= 0){
        printf("No data from standard input.<p>\n");
    }else{
        int i,ch;
        printf("Standard input:<br>\n<pre>\n");
                for (i = 0; i < len; i++) {
        if ((ch = getchar()) < 0) {                printf("Error: Not enough bytes received on standard input<p>\n");
                break;
          }                                                                                                                                                                                                     
                  putchar(ch);
              }
              printf("\n</pre><p>\n");
    }
        printEnv("Request environment",environ);
        printEnv("Initial environment",initialEnv);
    }
    return 0;
}
HelloWorld demo
#include<stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include<fcgi_stdio.h>
#include<iostream>

using namespace std;

int main()
{

  int count = 0;
  int rt = 0;
  FCGX_Init();
  FCGX_Request request;
  FCGX_InitRequest(&request,0,0);
  while(true)
  {
       if((rt=FCGX_Accept_r(&request))<0)
       { 
         cerr << "FCGX_Accept_r errno :"  << rt ;
         break;
       }

       FCGX_FPrintF(request.out,"Content-type: text/html\r\n"
       "\r\n"
       "<title>FastCGI Hello!</title>"
       "<h1> FastCGI Hello!</h1>"
       "<br /> Request count :%d "
       "<br /> Process ID:%d ",count,getpid());
   //  这里不用主动Finish 再次调用Accept的时候
   //它会帮我们Finish上次的请求        
  }
  return 0;
}

nginx配置

大家如果跑我的列子需要加nginx加入如下配置

        location = /demo.cgi {
          fastcgi_pass 127.0.0.1:9000;
          fastcgi_index index.cgi;
          include fastcgi.conf;
        }

实战图

hellocgi

这里写图片描述

这里写图片描述

echo cgi
FastCGIecho
Requestnumber2,ProcessID:2964

Nodatafromstandardinput.

Requestenvironment:

FCGI_ROLE=RESPONDER
SCRIPT_FILENAME=/usr/local/nginx/html/demo.cgi
QUERY_STRING=a&1
REQUEST_METHOD=GET
CONTENT_TYPE=
CONTENT_LENGTH=
SCRIPT_NAME=/demo.cgi
REQUEST_URI=/demo.cgi?a&1
DOCUMENT_URI=/demo.cgi
DOCUMENT_ROOT=/usr/local/nginx/html
SERVER_PROTOCOL=HTTP/1.1
GATEWAY_INTERFACE=CGI/1.1
SERVER_SOFTWARE=nginx/1.7.7
REMOTE_ADDR=127.0.0.1
REMOTE_PORT=59860
SERVER_ADDR=127.0.0.1
SERVER_PORT=80
SERVER_NAME=localhost
REDIRECT_STATUS=200
HTTP_HOST=127.0.0.1
HTTP_USER_AGENT=Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0
HTTP_ACCEPT=text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
HTTP_ACCEPT_LANGUAGE=en-GB,en;q=0.5
HTTP_ACCEPT_ENCODING=gzip, deflate
HTTP_CONNECTION=keep-alive
HTTP_UPGRADE_INSECURE_REQUESTS=1

Initialenvironment:

HOSTNAME=localhost.localdomain
SELINUX_ROLE_REQUESTED=
SHELL=/bin/bash
TERM=xterm
HISTSIZE=1000
SSH_CLIENT=192.168.248.1 50928 22
SELINUX_USE_CURRENT_RANGE=
QTDIR=/usr/lib64/qt-3.3
QTINC=/usr/lib64/qt-3.3/include
SSH_TTY=/dev/pts/0
USER=yutian
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.tbz=01;31:*.tbz2=01;31:*.bz=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:
LD_LIBRARY_PATH=/usr/local/lib:
PATH=/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/yutian/bin:/usr/local/git/bin:/home/yutian/bin
MAIL=/var/spool/mail/yutian
_=./sbin/spawn-fcgi
PWD=/usr/local/nginx
LANG=en_US.UTF-8
SELINUX_LEVEL_REQUESTED=
HISTCONTROL=ignoredups
SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass
HOME=/home/yutian
SHLVL=1
LOGNAME=yutian
CVS_RSH=ssh
QTLIB=/usr/lib64/qt-3.3/lib
SSH_CONNECTION=192.168.248.1 50928 192.168.248.129 22
LESSOPEN=|/usr/bin/lesspipe.sh %s
PKG_CONFIG_PATH=/usr/local/lib/:/usr/local/lib/pkgconfig:/usr/local/lib/pkgconfig:/usr/local/lib/pkgconfig:
DISPLAY=localhost:10.0
G_BROKEN_FILENAMES=1

相关阅读

Spawn-FCGI安装 Nginx与fastcgi简单案例

获取spawn-fcgi编译安装包, 在 http://redmine.lighttpd.net/projects/spawn-fcgi/wiki 上可 以获取当 前最新的版本。tar -zxvf s

分享到:

栏目导航

推荐阅读

热门阅读