博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
FastCGI学习总结
阅读量:5301 次
发布时间:2019-06-14

本文共 9167 字,大约阅读时间需要 30 分钟。

什么是FastCGI

FastCGI :Fast Common Gateway Interface(快速通用网关接口),它是CGI的增强版。FastCGI是一个快速、开放和安全的web server接口,解决了传统CGI的性能问题,却又没有带来编程的复杂性。老的CGI程序可以很轻易的移植成FastCGI程序。

FastCGI的技术原理

如果想了解FastCGI的技术原理就要了解何为"短生存期应用程序",何为"长生存期应用程序"

先从CGI技术开刀,以下是CGI技术的理论:每次当客户请求一个CGI的时候,Web服务器就请求操作系统生成一个新的CGI进程。当CGI满足要求后,服务器就杀死这个进程。服务器对客户端的每个请求都要重复这样的过程。

而FastCGI技术的理论为:FastCGI程序一旦产生后,他可以持续工作,足够满足客户的请求直到被明确的终止。如果你希望通过协同处理来提高程序的性能,你可以请求Web服务器运行多个FastCGI 应用程序的副本。 CGI就是所谓的短生存期应用程序,FastCGI就是所谓的长生存期应用程序。

由于FastCGI程序并不需要不断的产生新进程,可以大大降低服务器的压力。并且产生较高的应用效率。

FastCGI的特点

  1. 打破传统页面处理技术

传统的页面处理技术,程序必须与Web服务器或Application服务器处于同一台服务器中。这种历史已经早N年被FastCGI技术所打破,FastCGI技术的应用程序可以被安装在服务器群中的任何一台服务器,而通过TCP/IP协议与Web服务器通讯,这样做既适合开发大型分布式Web群,也适合高效数据库控制。

 

  1. 明确的请求模式

CGI技术没有一个明确的角色,在FastCGI程序中,程序被赋予明确的角色(响应器角色Responder、认证器角色Authorizer、过滤器角色Filter)。

 

  1. 独立性 

架构独立性:FastCGI接口并不绑定特定的应用服务器架构,应用既可以是单线程的也可是多线程的。

进程独立性:FastCGI进程是独立于服务器的进程,对FastCGI进程的调试不影响服务器。同理,FastCGI进程的崩溃也不至于服务器崩溃。

语言独立性:FastCGI技术目前支持语言有:C/C++JavaPerlTclPythonSmallTalkRuby

 

如何开发FastCGI程序

实现细节

先来看看传统CGI是怎么做的,如下图:

 

图一:CGI的数据流

CGI应用是通过标准的POSIX(stdin, stdout, stderr和环境变量)加上环境变量,来与HTTP服务器进行通信。

 

与CGI类似,FastCGI采用的方法是:在HTTP进程和FastCGI进程之间创建一个全双工的连接,数据报通过FastCGI协议封装在两个进程之间传递。

stdin和环境变量被封装在连接的输入部分;stdoutstderr被封装在连接的输出部分。

因此,作为输入端,FastCGI程序从连接上接收数据,解包,分离出stdin和环境变量,然后调用应用处理逻辑。作为输出端,FastCGIFastCGI协议打包stdoutstderr,发送给HTTP服务器处理。

 

由于FastCGI应用不要求和HTTP服务器运行在同一个节点上,因此,FastCGI支持两种形式的连接:1)流管道,用于在同一个节点上的通信;2TCP流,用于不同节点上的通信。

下图是FastCGI应用和HTTP服务器不在同一个机器上的数据流图:

 

图二:FastCGIHTTP不在同一节点的数据流

程序框架

不同于CGI程序的单次执行特性,FastCGI的主程序框架有一个循环,如下:

 

Initialize application;

while(FCGI_Accept() >= 0) {
Process request;
}

 

初始化部分,只执行一次,所以常常把一些耗时的工作放在此处理,如:打开和连接数据库,计算表和位图值等。

另外初始化部分,还完成环境变量初始化等工作。

 

然后,程序阻塞在FCGI_Accep()调用上,一旦有连接上了就处理,否则就阻塞。

 

一个简单的FastCGI程序实例:

#include "fcgi_stdio.h" /* fcgi library; put it first*/

#include <stdlib.h>

 

int count;

 

void initialize(void)

{

  count=0;

}

 

void main(void)

{

/* Initialization. */  

  initialize();

 

/* Response loop. */

  while (FCGI_Accept() >= 0)   {

    printf("Content-type: text/html\r\n"

           "\r\n"

           "<title>FastCGI Hello! (C, fcgi_stdio library)</title>"

           "<h1>FastCGI Hello! (C, fcgi_stdio library)</h1>"

           "Request number %d running on host <i>%s</i>\n",

            ++count, getenv("SERVER_HOSTNAME"));

  }

}

另外一个例子,是从stdin和环境变量获取表单参数的例子,由于代码过长,以附件形式给出:

 

 

附录:CGI常用环境变量

环境变量

说明

ALL_HTTP

未包括在本表格中给出的变量内的所有HTTP标题,如:这个变量来自表格HTTP_<标题栏名称>

QUERY_STRING

传递给程式的 query 信息,即:在指向URL中跟在问号(?)后的信息

REMOTE_HOST

使用者发出 request 的远端 host 名称

REMOTE_ADDR

使用者发出 request 的远端 IP 位址

AUTH_TYPE

用来确定使用者合法性的监定方法

REMOTE_USER

使用者的合法名称

REMOTE_IDENT

发出 request 的使用者

CONTENT_TYPE

query 信息中的 MIME 类型

CONTENT_LENGTH

以字节为单位的从客户端接收来的脚步长度

HTTP_FORM

使用者发出 request 的电子邮件讯息

HTTP_ACCEPT

client 可以接受的 MIME 类型列表

HTTP_COOKIE

与你站点打交道的客户的任何cookie(存储片)集合

HTTP_USER_AGENT

client 用来发出 request 的浏览器

GATEWAY_INTERFACE

Server 使用的 CGI 版本

SERVER_NAME

Server host 名称或 IP 位址

SERVER_SOFTWARE

回应 client request Server 软体名称和版本

SERVER_PROTOCOL

传递资讯所用的协定名称或版本

SERVER_PORT

Server 正在执行的 port number

SERVER_PORT_SECURE

值为01,值1表示请求出现在加密端口

URL

请求的URL地址

REQUEST_METHOD

发出 request 的方法

PATH_INFO

传递给 CGI 程式的额外路径

PATH_TRANSLATED

存在 PATH_INFO 中的给定路径的传递版本

SCRIPT_NAME

程式执行时的 virtual path

DOCUMENT_ROOT

网路提供的文件服务所在路径

HTTP_REFERER

在读取 CGI 程式前,client 所指的文件 URL

 

 

这个模块允许nginxFastCGI协同工作,并且控制哪些参数将被安全传递。

例:

location /

 

{  

fastcgi_pass   localhost:9000;  

fastcgi_index  index.php;   

fastcgi_param  SCRIPT_FILENAME  /home/www/scripts/php$fastcgi_script_name;  

fastcgi_param  QUERY_STRING     $query_string;  

fastcgi_param  REQUEST_METHOD   $request_method;  

fastcgi_param  CONTENT_TYPE     $content_type;  

fastcgi_param  CONTENT_LENGTH   $content_length;

}

 

一个在缓存中的实例:

 

http

{  

fastcgi_cache_path   /path/to/cache  

levels=1:2          keys_zone=NAME:10m      inactive=5m   clean_time=2h00m;  

server

{    

location /

{      

 

fastcgi_pass    http://127.0.0.1;     

fastcgi_cache   NAME;      

fastcgi_cache_valid   200 302  1h;      

fastcgi_cache_valid   301      1d;      

fastcgi_cache_valid   any      1m;      

fastcgi_cache_min_uses  1;      

fastcgi_cache_use_stale error  timeout invalid_header http_500;    

}

}

}

 

0.7.48以后,缓存遵循后端服务器的Cache-Control, Expires等。

 

fastcgi_buffers

语法:fastcgi_buffers the_number is_size;

默认值:fastcgi_buffers 8 4k/8k;

使用字段:http, server, location

这个参数指定了从FastCGI服务器到来的应答,本地将用多少和多大的缓冲区读取,默认这个参数等于分页大小,根据环境的不同可能是4K, 8K16K

 

fastcgi_buffer_size

语法:fastcgi_buffer_size the_size ;

默认值:fastcgi_buffer_size 4k/8k ;

使用字段:http, server, location

这个参数指定将用多大的缓冲区来读取从FastCGI服务器到来应答的第一部分。

通常来说在这个部分中包含一个小的应答头。

默认这个值为fastcgi_buffers指令中的每块大小,可以将这个值设置更小。

 

fastcgi_cache

语法:fastcgi_cache zone;

默认值:off

使用字段:http, server, location

为缓存实际使用的共享内存指定一个区域,相同的区域可以用在不同的地方。

 

fastcgi_cache_key

语法:fastcgi_cache_key line ;

默认值:none

使用字段:http, server, location

设置缓存的关键字,如:

fastcgi_cache_key localhost: 9000 $ request_uri;

 

fastcgi_cache_methods

语法:fastcgi_cache_methods [GET HEAD POST];

默认值:fastcgi_cache_methods GET HEAD;

使用字段:main,http,location

无法禁用GET/HEAD ,即使你只是这样设置:

fastcgi_cache_methods  POST;

 

fastcgi_cache_min_uses

语法:fastcgi_cache_min_uses n

默认值:fastcgi_cache_min_uses 1

使用字段:http, server, location

 

fastcgi_cache_path

语法:fastcgi_cache_path /path/to/cache [levels=m:n keys_zone=name:time inactive=time clean_time=time]

默认值:none

使用字段:http, server, location

 

fastcgi_cache_use_stale

语法:fastcgi_cache_use_stale [updating|error|timeout|invalid_header|http_500]

默认值:fastcgi_cache_use_stale off;

使用字段:http, server, location

 

fastcgi_cache_valid

语法:fastcgi_cache_valid [http_error_code|time]

默认值:none

使用字段:http, server, location

 

fastcgi_index

语法:fastcgi_index file

默认值:none

使用字段:http, server, location

如果URI以斜线结尾,参数将加到URI后面,这个值将存储在变量$fastcgi_script_name中。

 

fastcgi_hide_header

语法:fastcgi_hide_header name

使用字段:http, server, location

默认情况下nginx不会将来自FastCGI服务器的"Status""X-Accel-..."头传送到客户端,这个参数也可以隐藏某些其它的头。

如果必须传递"Status""X-Accel-..."头,则必须使用fastcgi_pass_header强制其传送到客户端。

 

fastcgi_ignore_client_abort

语法:fastcgi_ignore_client_abort on|off

默认值:fastcgi_ignore_client_abort off

使用字段:http, server, location

如果当前连接请求FastCGI服务器失败,为防止其与nginx服务器断开连接,可以用这个指令。

 

fastcgi_intercept_errors

语法:fastcgi_intercept_errors on|off

默认值:fastcgi_intercept_errors off

使用字段:http, server, location

这个指令指定是否传递4xx5xx错误信息到客户端,或者允许nginx使用error_page处理错误信息。

你必须明确的在error_page中指定处理方法使这个参数有效,正如Igor所说“如果没有适当的处理方法,nginx不会拦截一个错误,

这个错误不 会显示自己的默认页面,这里允许通过某些方法拦截错误。

 

fastcgi_max_temp_file_size

语法:fastcgi_max_temp_file_size 0

默认值:?

使用字段:?

根据源代码关闭FastCGI缓冲。

 

fastcgi_param

语法:fastcgi_param parameter value

默认值:none

使用字段:http, server, location

指定一些传递到FastCGI服务器的参数。

可以使用字符串,变量,或者其组合,这里的设置不会继承到其他的字段,设置在当前字段会清除掉任何之前的定义。

下面是一个PHP需要使用的最少参数:

fastcgi_param  SCRIPT_FILENAME  /home/www/scripts/php$fastcgi_script_name;  fastcgi_param  QUERY_STRING     $query_string;

PHP使用SCRIPT_FILENAME参数决定需要执行哪个脚本,QUERY_STRING包含请求中的某些参数。

如果要处理POST请求,则需要另外增加三个参数:

fastcgi_param  REQUEST_METHOD   $request_method;  

fastcgi_param  CONTENT_TYPE     $content_type;  

fastcgi_param  CONTENT_LENGTH   $content_length;

如果PHP在编译时带有--enable-force-cgi-redirect,则必须传递值为200REDIRECT_STATUS参数:

fastcgi_param  REDIRECT_STATUS  200;

 

fastcgi_pass

语法:fastcgi_pass fastcgi-server

默认值:none

使用字段:http, server, location

指定FastCGI服务器监听端口与地址,可以是本机或者其它:

fastcgi_pass   localhost:9000;

使用Unix socket:

fastcgi_pass   unix:/tmp/fastcgi.socket;

同样可以使用一个upstream字段名称:

upstream backend  

{  

server   localhost:1234;

}

fastcgi_pass   backend;

 

fastcgi_pass_header

语法:fastcgi_pass_header name

默认值:none

使用字段:http, server, location

 

fastcgi_read_timeout

语法:fastcgi_read_timeout time

默认值:60

使用字段:http, server, location

前端FastCGI服务器的响应超时时间,如果有一些直到它们运行完才有输出的长时间运行的FastCGI进程,或者在错误日志中出现前端服务器响应超时

 错误,可能需要调整这个值。

 

fastcgi_redirect_errors

语法:fastcgi_redirect_errors on|off

将来自fastcgi_intercept_errors的错误重命名。参数传递到FastCGI服务器。

请求头以参数的形式传递到FastCGI服务器,在FastCGI的应用程序或者脚本中运行,这些参数通常是环境变量的形式,例如:User-agent

头是以HTTP_USER_AGENT形式转发,另外可以借助fastcgi_param指令可以传递任意参数的HTTP请求头。

 

fastcgi_split_path_info

语法:fastcgi_split_path_info regex

使用字段:location

可用版本:0.7.31以上

location ~ ^(.+\.php)(.*)$

 

{

...

fastcgi_split_path_info ^(.+\.php)(.*)$;

fastcgi_param SCRIPT_FILENAME /path/to/php$fastcgi_script_name;

fastcgi_param PATH_INFO $fastcgi_path_info;

fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;

...

}

 

fastcgi_store

语法:fastcgi_store [on | off | path]

默认值:fastcgi_store off

使用字段:http, server, location

制定了存储前端文件的路径,参数on指定了将使用rootalias指令相同的路径,off禁止存储,此外,参数中可以使用变量使路径名更明确:

fastcgi_store   /data/www$original_uri;

应答中的"Last-Modified"头将设置文件的最后修改时间,为了使这些文件更加安全,可以将其在一个目录中存为临时文件,使用 fastcgi_temp_path指令。

这个指令可以用在为那些不是经常改变的后端动态输出创建本地拷贝的过程中。如:

location /images/

{  

root                 /data/www;  

error_page           404 = /fetch$uri;

}

location /fetch

 

{  

internal;   

fastcgi_pass           fastcgi://backend;

fastcgi_store          on;

fastcgi_store_access   user:rw  group:rw  all:r;  

fastcgi_temp_path      /data/temp;   

alias                  /data/www;

}

fastcgi_store并不是缓存,某些需求下它更像是一个镜像。

 

fastcgi_store_access

语法:fastcgi_store_access users:permissions [users:permission ...]

默认值:fastcgi_store_access user:rw

使用字段:http, server, location

这个参数指定创建文件或目录的权限,例如:

fastcgi_store_access  user:rw  group:rw  all:r;

如果要指定一个组的人的相关权限,可以不写用户,如:

fastcgi_store_access  group:rw  all:r;

·变量

$fastcgi_script_name

这个变量等于一个以斜线结尾的请求URI加上fastcgi_index给定的参数。可以用这个变量代替SCRIPT_FILENAME PATH_TRANSLATED,以确定php脚本的名称。

如下例,请求"/info/":

fastcgi_index  index.php;  fastcgi_param  SCRIPT_FILENAME  /home/www/scripts/php$fastcgi_script_name;

SCRIPT_FILENAME等于"/home/www/scripts/php/info/index.php"

转载于:https://www.cnblogs.com/centos-python/articles/8531932.html

你可能感兴趣的文章