正在加载中……
最新消息:欢迎大家访问,导航分类不完善,如果找不到自己想要的文章,可以通过【关键词】来进行搜索,^_^!

Nginx支持Perl、Java的安装与配置

Linux专题 REKFAN.COM 6151浏览 0评论

更多


实战Nginx与Perl、Java的安装与配置

Nginx的安装这里不再讲述,这假定Nginx的安装路径为/usr/local/nginx。

一、Perl(FastCGI)的安装

  1.获取wrapper程序

  读者可以从http://addcn.googlecode.com/svn/trunk/conf/nagios/nginx-fcgi.pl下载nginx-fcgi.pl文件,并放到/usr/local/nginx目录下。nginx-fcgi.pl是一个用Perl脚本写的wrapper实例,所以,操作系统必须要安装Perl程序以及相关模块。
nginx-fcgi.pl 文件内容:

#!/usr/bin/perl
#
#    author        Daniel Dominik Rudnicki
#    thanks to:    Piotr Romanczuk
#    email         daniel@sardzent.org
#    version       0.4.3
#    webpage       http://www.nginx.eu/
#
#    BASED @ http://wiki.codemongers.com/NginxSimpleCGI
#
#
# use strict;

use FCGI;
#perl -MCPAN -e 'install FCGI'
use Getopt::Long;
use IO::All;
use Socket;

sub init {
    GetOptions(
        "h"    => $help,
        "verbose!"=>$verbose,
        "pid=s"    => $filepid,
        "l=s" => $logfile,
        "S:s"   => $unixsocket,
        "P:i"   => $unixport
    ) or usage();
    usage() if $help;

    print "    Starting Nginx-fcgin" if $verbose;
    print "    Running with $> UID" if $verbose;
    print "    Perl $]" if $verbose;

    #if ( $> == "0" ) {
    #    print "ntERRORtRunning as a root!n";
    #    print "tSuggested not to do so !!!nn";
    #    exit 1;
    #}
    if ( ! $logfile ) {
        print "ntERRORt log file must declaredn"
        . "tuse $0 with option -l filenamenn";
        exit 1;
    }
    print "    Using log file $logfilen" if $verbose;
    "nn" >> io($logfile);
    addlog($logfile, "Starting Nginx-cfgi");
    addlog($logfile, "Running with $> UID");
    addlog($logfile, "Perl $]");
    addlog($logfile, "Testing socket options");

    if ( ($unixsocket && $unixport) || (!($unixsocket) && !($unixport)) ) {
        print "ntERRORtOnly one option can be used!n";
        print "tSuggested (beacuse of speed) is usage UNIX socket -S nn";
        exit 1;
    }
    if ($unixsocket) {
        print "    Daemon listening at UNIX socket $unixsocketn" if $versbose;
        addlog($logfile, "Deamon listening at UNIX socket $unixsocket");
        } else {
        print "    Daemon listening at TCP/IP socket *:$unixportn" if $verbose;
        #
        addlog($logfile, "Daemon listening at TCP/IP socket *:$unixport");
    }

    if ( -e $filepid ) {
        print "ntERRORt PID file $filepid already existsnn";
        addlog($logfile, "Can not use PID file $filepid, already exists.");
        exit 1;
    }

    if ( $unixsocket ) {
        print "    Creating UNIX socketn" if $verbose;
        $socket = FCGI::OpenSocket( $unixsocket, 10 );
        if ( !$socket) {
        print "    Couldn't create socketn";
        addlog($logfile, "Couldn't create socket");
        exit 1;
    }

    print "    Using UNIX socket $unixsocketn" if $verbose;
    } else {
        print "    Creating TCP/IP socketn" if $verbose;
        $portnumber = ":".$unixport;
        $socket = FCGI::OpenSocket( $unixport, 10 );
        if ( !$socket ) {
            print "    Couldn't create socketn";
            addlog($logfile, "Couldn't create socket");
            exit 1;
        }
        print " Using port $unixportn" if $verbose;
    }
    addlog($logfile, "Socket created");

    if ( ! $filepid ) {
        print "ntERRORt PID file must declaredn"
        . "tuse $0 with option -pid filenamenn";
        exit 1;
    }
    print "    Using PID file $filepidn" if $verbose;
    addlog($logfile, "Using PID file $filepid");

    my $pidnumber = $$;
    $pidnumber > io($filepid);
    print " PID number $$n" if $verbose;
    addlog($logfile, "PID number $pidnumber");
}

sub addzero {
    my ($date) = shift;
    if ($date < 10) {
        return "0$date";
    }
    return $date;
}
sub logformat {
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$iddst) = localtime(time);
    my $datestring;
    $year += 1900;
    $mon++;
    $mon  = addzero($mon);
    $mday = addzero($mday);
    $min  = addzero($min);
    $datestring = "$year-$mon-$mday $hour:$min";
    return($datestring);
}
sub addlog {
    my ($log_file, $log_message) = @_;
    my $curr_time = logformat();
    my $write_message = "[$curr_time]   $log_message";
    $write_message >> io($log_file);
    "n" >> io($log_file);
}

sub printerror {
    my $message = @_;
    print "n    Nginx FastCGItERRORn"
    . "t $messagenn";
    exit 1;
}
sub usage {
    print "n    Nginx FastCGI n"
    . "ntusage: $0 [-h] -S string -P intn"
    . "nt-htt: this (help) message"
    . "nt-S pathtt: path for UNIX socket"
    . "nt-P porttt: port number"
    . "nt-p filett: path for pid file"
    . "nt-l filett: path for logfile"
    . "nntexample: $0 -S /var/run/nginx-perl_cgi.sock -l /var/log/nginx/nginx-cfgi.log -pid /var/run/nginx-fcgi.pidnn";
    exit 1;
}

init;
#
END() { } BEGIN() { }
*CORE::GLOBAL::exit = sub { die "fakeexitnrc=".shift()."n"; }; eval q{exit};
if ($@) {
    exit unless $@ =~ /^fakeexit/;
};

# fork part
my $pid = fork();

if( $pid == 0 ) {
    &main;
    exit 0;
}

print " Forking worker process with PID $pidn" if $verbose;
addlog($logfile, "Forking worker process with PID $pid");
print " Update PID file $filepidn" if $verbose;
addlog($logfile, "Update PID file $filepid");
$pid > io($filepid);
print "    Worker process running.n" if $verbose;
addlog ($logfile, "Parent process $$ is exiting");
exit 0;

sub main {
    $request = FCGI::Request( *STDIN, *STDOUT, *STDERR, %req_params, $socket );
    if ($request) { request_loop()};
    FCGI::CloseSocket( $socket );
}
sub request_loop {
    while( $request->Accept() >= 0 ) {
        # processing any STDIN input from WebServer (for CGI-POST actions)
        $stdin_passthrough = '';
        $req_len = 0 + $req_params{'CONTENT_LENGTH'};
        if (($req_params{'REQUEST_METHOD'} eq 'POST') && ($req_len != 0) ){
            while ($req_len) {
                $stdin_passthrough .= getc(STDIN);
                $req_len--;   
            }
        }

        # running the cgi app
        if ( (-x $req_params{SCRIPT_FILENAME}) &&
            (-s $req_params{SCRIPT_FILENAME}) &&
            (-r $req_params{SCRIPT_FILENAME})
        ){
            foreach $key ( keys %req_params){
                $ENV{$key} = $req_params{$key};
            }
            if ( $verbose ) {
                addlog($logfile, "running $req_params{SCRIPT_FILENAME}");
            }

            # http://perldoc.perl.org/perlipc.html#Safe-Pipe-Opens
            #
            open $cgi_app, '-|', $req_params{SCRIPT_FILENAME}, $stdin_passthrough or print("Content-type: text/plainrnrn"); print "Error: CGI app returned no output - Executing $req_params{SCRIPT_FILENAME} failed !n"; # addlog($logfile, "Error: CGI app returned no output - Executing $req_params{SCRIPT_FILENAME} failed !");

            if ($cgi_app) {
                print <$cgi_app>;
                close $cgi_app;
            }
        } else {
            print("Content-type: text/plainrnrn");
            print "Error: No such CGI app - $req_params{SCRIPT_FILENAME} may not exist or is not executable by this process.n";
            addlog($logfile, "Error: No such CGI app - $req_params{SCRIPT_FILENAME} may not exist or is not executable by this process.");
        }
    }
}

2.安装相关的系统支持模块

  可以从http://search.cpan.org下载所需的相应模块,然后进行安装。

(1)安装 FCGI 模块
[root@FH21-Test-Server src]# wget http://search.cpan.org/CPAN/authors/id/F/FL/FLORA/FCGI-0.74.tar.gz
[root@FH21-Test-Server src]# tar zxvf FCGI-0.74.tar.gz
[root@FH21-Test-Server src]# cd FCGI-0.74
[root@FH21-Test-Server FCGI-0.74]# perl Makefile.PL
[root@FH21-Test-Server FCGI-0.74]# make && make install

(2)安装 IO 模块
[root@FH21-Test-Server src]# wget http://search.cpan.org/CPAN/authors/id/G/GB/GBARR/IO-1.25.tar.gz
[root@FH21-Test-Server src]# tar zxvf IO-1.25.tar.gz
[root@FH21-Test-Server src]# cd IO-1.25
[root@FH21-Test-Server IO-1.25]# perl Makefile.PL
[root@FH21-Test-Server IO-1.25]# make && make install

(3)安装 IO-ALL 模块
[root@FH21-Test-Server src]# wget http://search.cpan.org/CPAN/authors/id/F/FR/FREW/IO-All-0.57.tar.gz
[root@FH21-Test-Server src]# tar zxvf IO-All-0.57.tar.gz
[root@FH21-Test-Server src]# cd IO-All-0.57
[root@FH21-Test-Server IO-All-0.57]# perl Makefile.PL    
[root@FH21-Test-Server IO-All-0.57]# make && make install

3.编写nginx-fcgi启动脚本

  仅仅有wrapper文件是不够的,还需要一个脚本来创建socket、启动wrapper以及将wrapper和socket绑定,下面通过一个shell脚本来完成这一系列工作。
nginx-fcgi 文件内容:

#!/bin/bash
# nginx 路径
nginxroot=/usr/local/nginx
# nginx 用户
nginxuser=www
#########################################
    start ()
    {
    chown $nginxuser.root $nginxroot/logs
    echo "$nginxroot/nginx-fcgi.pl -l $nginxroot/logs/nginx-fcgi.log -pid $nginxroot/logs/nginx-fcgi.pid  -S  $nginxroot/logs/nginx-fcgi.sock" >>$nginxroot/nginx_fcgi.sh
    chown nobody.nobody $nginxroot/nginx_fcgi.sh
    chmod 755 $nginxroot/nginx_fcgi.sh
    sudo -u nobody $nginxroot/nginx_fcgi.sh
    echo "start nginx-fcgi done"
    }
 
    stop ()
    {
    kill $(cat $nginxroot/logs/nginx-fcgi.pid)
    rm $nginxroot/logs/nginx-fcgi.pid 2>/dev/null
    rm $nginxroot/logs/nginx-fcgi.sock 2>/dev/null
    rm $nginxroot/nginx_fcgi.sh 2>/dev/null
    echo "stop nginx-fcgi done"
    }
 
    case $1 in
    stop)
    stop
    ;;
 
    start)
    start
    ;;
 
    restart)
    stop
    start
    ;;
 
    *)
    echo $"Usage: perl-cgi {start|stop|restart}"
        exit 1
    esac

在nginx-fcgi中,变量nginxroot指定Nginx的安装目录,nginx-fcgi.sock是生成的文件sock, nobody为运行nginx_fcgi进程的用户,这个用户要和运行Nginx的用户一致。

  配置完脚本后,将此文件放到/usr/local/nginx目录下,接着通过如下方式管理nginx-fcgi进程。
[root@localhost root]#chmod 755 /usr/local/nginx/nginx-fcgi.pl
[root@localhost root]#chmod 755 /usr/local/nginx/nginx-fcgi
[root@localhost root]#/usr/local/nginx/nginx-fcgi start|stop|restart

二、为Nginx添加FCGI支持

  修改Nginx配置文件,在server虚拟主机中添加如下配置:

 location ~ .cgi$ {   
    root        html;   
    fastcgi_pass    unix:/usr/local/nginx/logs/nginx-fcgi.sock;   
    fastcgi_index   index.cgi;   
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;   
    include         fastcgi_params;   
}  

在这个location配置中,Nginx与FastCGI的通信方式为Unix Socket。根据经验,IP Socket在高并发访问下比Unix Socket稳定,但Unix Socket速度要比IP Socket快。 “$document_root”是虚拟主机的根目录,在这里是/usr/local/nginx/html目录。

三、测试Nginx +Perl(FastCGI)

  所有配置工作完成后,即可启动服务了。首选启动nginx-fcgi进程,操作如下:

  /usr/local/nginx/nginx-fcgi start

  然后启动nginx服务。

  /usr/local/nginx/sbin/nginx

  下面在/usr/local/nginx/html目录下创建一个test.cgi的文件。

# disable filename globbing
set -f
echo "Content-type: text/plain; charset=iso-8859-1"
echo
 
echo CGI/1.0 test script report:
echo
 
echo argc is $#. argv is "$*".
echo
 
echo SERVER_SOFTWARE = $SERVER_SOFTWARE
echo SERVER_NAME = $SERVER_NAME
echo GATEWAY_INTERFACE = $GATEWAY_INTERFACE
echo SERVER_PROTOCOL = $SERVER_PROTOCOL
echo SERVER_PORT = $SERVER_PORT
echo REQUEST_METHOD = $REQUEST_METHOD
echo REMOTE_ADDR = $REMOTE_ADDR

接着通过浏览器访问test.cgi文件,如果显示与下面类似的信息,表明Nginx+Perl环境搭建成功:

CGI/1.0 test script report:
argc is 1. argv is .
SERVER_SOFTWARE = nginx/0.7.65
SERVER_NAME = localhost
GATEWAY_INTERFACE = CGI/1.1
SERVER_PROTOCOL = HTTP/1.1
SERVER_PORT = 8000
REQUEST_METHOD = GET
REMOTE_ADDR = 123.76.159.197

四、搭建Nginx+Java环境

  Apache对Java的支持很灵活,他们的结合度也很高,例如Apache+Tomcat和Apache+resin等都可以实现对Java应用的支持。Apache一般采用一个内置模块来和Java应用服务器打交道。与Apache相比,Nginx在配合Java应用服务器方面,耦合度很低,它只能通过自身的反向代理功能来实现与Java应用服务器的支持,这恰恰是Nginx的一个优点,耦合度的降低,可以使Nginx与Java服务器的相互影响降到最低。

  接下来通过Nginx+Tomcat的实例来讲解Nginx对Java的支持。Tomcat在高并发环境下处理动态请求时性能很低,而在处理静态页面更加脆弱。虽然Tmcat的最新版本支持epoll,但是通过Nginx来处理静态页面要比通过Tomcat处理在性能方面好很多。

  Nginx可以通过两种方式来实现与Tomcat的耦合。

  将静态页面请求交给Nginx,动态请求交给后端Tomcat处理。

  将所有请求都交给后端的Tomcat服务器处理,同时利用Nginx自身的负载均衡功能,进行多台Tomcat服务器的负载均衡。

  下面通过两个配置实例分别讲述这两种实现Nginx与Tomcat耦合的方式。

  1.动态页面与静态页面分离实例

  这里假定Tomcat服务器的IP地址为192.168.1.130,同时tomcat服务器开放的服务端口为8080,Nginx相关配置代码如下:

server {  
    listen 80;  
    server_name blog.rekfan.com;  
    root /web/www/html;
 
location /img/ {  
    alias /web/www/html/img/;  
}
 
location ~ (.jsp)|(.do)$ {  
        proxy_pass http://192.168.1.130:8080;  
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        client_max_body_size 10m;
        client_body_buffer_size 128k;
        proxy_connect_timeout 90;
        proxy_send_timeout 90;
        proxy_read_timeout 90;
        proxy_buffer_size 4k;
        proxy_buffers 4 32k;
        proxy_busy_buffers_size 64k;
        proxy_temp_file_write_size 64k;
}  
 
}

    在这个实例中,首先定义了一个虚拟主机blog.rekfan.com,然后通过location指令将/web/www/html/img/目录下的静态文件交给Nginx来完成,最后一个location指令将所有以.jsp、.do结尾的文件都交给Tomcat服务器的8080端口来处理,即http://192.168.1.130:8080。

  需要特别注意的是,在location指令中使用正则表达式后,proxy_pass后面的代理路径不能含有地址链接,也就是不能写成http://192.168.1.130:8080/,或者类似http://192.168.1.130:8080/jsp的形式。在location指令不使用正则表达式时,没有此限制。

  2.多个Tomcat负载均衡实例

  这里假定有三台Tomcat服务器,分别开放不同的端口,地址分别是:

192.168.1.131:8000
192.168.1.132:8080
192.168.1.133:8090   

Nginx的相关配置代码如下:

upstream mytomcats {  
    server 192.168.1.131:8000;  
    server 192.168.1.132:8080;
    server 192.168.1.133:8090;
}  
 
server {  
    listen 80;  
    server_name blog.rekfan.com;  
 
location ~* .(jpg|gif|png|swf|flv|wma|wmv|asf|mp3|mmf|zip|rar)$ {  
    root /web/www/html/;  
}
 
location / {
        proxy_pass http://mytomcats;  
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        client_max_body_size 10m;
        client_body_buffer_size 128k;
        proxy_connect_timeout 90;
        proxy_send_timeout 90;
        proxy_read_timeout 90;
        proxy_buffer_size 4k;
        proxy_buffers 4 32k;
        proxy_busy_buffers_size 64k;
        proxy_temp_file_write_size 64k;
}  
 
}

    在这个实例中,首先通过upstream定义一个负载均衡组,组名为mytomcats,组的成员就是上面指定的三台Tomcat服务器;接着通过server指令定义一个blog.rekfan.com的虚拟主机;然后通过location指令以正则表达式的方式将指定类型的文件全部交给Nginx去处理;最后将其它所有请求全部交给负载均衡组来处理。

  这里还有一点需要注意,如果在location指令使用正则表达式后再用alias指令,nginx是不支持的。

转载请注明:|REKFAN|系统运维| » Nginx支持Perl、Java的安装与配置

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址