Nginx下配置FastCGI原理

来源:互联网 发布:网络连接配置异常 编辑:程序博客网 时间:2024/05/21 06:58

这是一篇讲述怎样在Nginx下配置fastcgi的文章。

适用

Nginx通过fastcgi调用python, Perl和C++等写的CGI程序。PHP有PHP-FPM (FastCGI Process Manager),这个对PHP来说更好的FastCGI进程管理器,关于PHP-FPM的更多信息,请Google php-fpm+nginx。

原理

Nginx并不提供支持对外部程序的直接调用或者解析(所以缺少像apache里的mod_php这样的模块),所有的外部程序(包括PHP)必须通过fastcgi接口来调用,在Linux下接口是socket (文件socket或者Internet socket)。所以为了调用CGI程序,我们需要一个fastcgi的wrapper,这个wrapper绑定在某个固定socket上(比如端口或者文件socket),当nginx将CGI请求发送给这个socket的时候,wrapper接纳请求并fork一个新的线程,这个线程调用外部的程序或者解释器处理脚本并读取返回值,而wrapper再将返回的数据(网页或者图片等)通过fastcgi将数据通过那个固定的socket传递给nginx。示意图如下:

Ningx的FastCGI原理

所以,我们首先需要一个wrapper,这个wrapper需要完成的工作:

  1. 通过调用fastcgi(库)的函数通过socket和ningx通信(读写socket是fastcgi内部实现的功能,对wrapper是非透明的)
  2. 调度thread,进行fork和kill
  3. 和application进行通信

Wrapper的实现

在Nginx的官方wiki中给出了一个Perl写的wrapper例子,显然这需要安装Perl和必要的module(比如FCGI)。为了追求效率,我们希望有一个C写的wrapper。我找到了这个fcgiwrap项目。

只有wrapper还是不够的,我们需要一个脚本来建立socket,启动wrapper以及将wrapper和socket绑定。你可以从我的服务器上下载这个C的wrapper和启动脚本。启动脚本spawn-fcgi的内容如下:

帮助
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!/usr/bin/perl
 
use strict;
use warnings FATAL => qw( all );
 
use IO::Socket::UNIX;
 
my $bin_path = '/usr/sbin/fcgiwrap';
my $socket_path = $ARGV[0] || '/var/run/nginx/nginx-fcgi.sock';
my $num_children = $ARGV[1] || 4;
 
close STDIN;
 
unlink $socket_path;
my $socket = IO::Socket::UNIX->new(
 Local => $socket_path,
 Listen => 100,
);
 
die"Cannot create socket at $socket_path: $!\n" unless $socket;
 
for(1 .. $num_children) {
 my $pid = fork;
 die"Cannot fork: $!" unless defined $pid;
 nextif$pid;
 
 exec$bin_path;
 die"Failed to exec $bin_path: $!\n";
}

你需要修改脚本中高亮的三行,分别是你编译后的fcgiwrap执行文件,domain socket的位置和同时运行的fcgiwrap进程的个数。后两个参数也可以通过调用spawn-fcgi的命令行传递。

建议你用www-data或者nginx等低权限帐号而不是root来运行这个spawn-fcgi脚本,这要求该帐号能够读写那个socket文件所在的文件夹(上面的例子中是 /var/run/nginx/ )。

如果你的机器没有Perl,你可以下载编译一个C写的spawn-fcgi (本地备份),这是lighttpd中的一个子项目,调用这个C版本的spawn-fcgi时可以通过命令行指定domain socket等信息。

Nginx配置

相应地,nginx中需要做如下配置。在你的site文件的server{…}中加入:

帮助
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
location ~ ^.+\.cgi$ {
 root   /var/www/yoursite.com;
 gzip off; #gzip makes scripts feel slower since they have to complete before getting gzipped
 fastcgi_pass  unix:/var/run/nginx/nginx-fcgi.sock;
 fastcgi_read_timeout    5m;
 fastcgi_param SCRIPT_FILENAME /var/www/yoursite$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;
 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  GATEWAY_INTERFACE  CGI/1.1;
 fastcgi_param  SERVER_SOFTWARE    Nginx;
 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;
 }

你需要把上面高亮的三行修改为你的配置。注意root一行是必须的,否则wrapper会报错。

原创粉丝点击