让Web服务器支持Perl
2013-06-20 15:18:18

本站赞助商链接,请多关照。 Perl 是一门出现时间较长的且在Unix世界上存在多年的中级编程语言,在很多领域都能看见它的影子。跟其它脚本语言一样,它也有它的个性,当然你并不一定喜欢;它一度是CGI世界里的老大,近年里也崛起其它的编程语言,它们分去了Perl所占有的份额。它们或学习于Perl,像Ruby,或对Perl不服,想超过它的Python,或想在某一领域里取代之,像PHP等。有竞争才有发展,最新版本的Perl 6就让人觉得耳目一新,当然目前还是Perl 5的生产环境,这也将持续多年。

在Web大行其道的今天,Perl仍发挥着它的光茫,有相当多的组件或框架可供选择。它们具备支持当今流行的Html5等新特性的功能,像Mojolicious这个项目。与其它框架不一样的是,它本身带有http服务器的功能,支持PSGI扩展,所以后端的动态解析服务器不是必需的。

本文试着讨论下各个应用环境下web服务器对perl的支持。个人经验有限,不足之处日后补充。从web服务自身的发展与后端开发的进步来看,主要有两种方式:传统的cgi及改良的fastcgi、嵌入到web服务器内部


传统的cgi及改良的fastcgi

CGI方式

在Web开始发展之初,使用的是这种方法,它有较多缺点(像效率)。这才导致了对它的轻度改良(像FastCGI之类)和重度的改良(彻底放弃这种方式而使用内嵌式)。

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

可见这种方式是低效的,像到数据库的连接,在用户访问量增大时响应会很慢。

改良的CGI
这种改进的示例有很多,FastCGI是较早的改良派。
FastCGI程序并不需要不断的产生新进程,可以大大降低服务器的压力,并且产生较高的应用效率。当负载很低时,CGI能很好地工作。

注意:FastCGI更像是技术规范,FastCGI技术目前支持语言有:C/C++、Java、Perl、Tcl、Python、SmallTalk、Ruby等。目前主流的Web服务器Apache、IIS、Nginx等完全支持。

PHP从5.2开始使用php-fpm来取代老的php-cgi方式来提供CGI支持,前者在某种程度上讲就属于这个改良的CGI模式。目前也有相当多的php站点从apache+mod_php方式转为nginx+php-fpm方式了。而前者就是下面我们要讲到的嵌入到web服务器内部的方式。

嵌入到web服务器内部
这种方法是对cgi模式的彻底否定,它将解析处理动态内容放到Web服务器内部来完成,与Web服务器共享地址空间。

这样可以缓存部分变量值或连接句柄,同一内存地址内执行效率和稳定性会有所提升;但缺点也是易见的:更多的内存、高并发时效率会比CGI模式差、相关的动态语言必须适用Web服务器的API(通用性差)。

两种动态语言的解析模式各有优缺点,但随着轻量级的Web服务器(nginxlighttpd)崛起,让改良派的cgi方式百花齐放。

这些像:
Perl->PSGI/Plack

Python->WSGI

Ruby->Rack


这些方法协议一般都内置于主流的框架之中。

介绍了关于后端动态的执行方式后,我们着重介绍在apache、nginx Web服务器支持Perl的方式方法。

一、Apache
它应该算是对Perl支持最好的独立Web服了,它们发布的时间较长,相互磨合地很好。
1、cgi
传统的cgi方式已经不在推荐使用了,对应在模块为:mod_cgid,改进的cgi方式有:libapache2-mod-fcgid、libapache2-mod-scgi、libapache2-mod-speedycgi、libapache2-mod-fastcgi

libapache2-mod-fcgid
An alternative module compat with mod_fastcgi
mod_fcgid is a high performance alternative to mod_cgi or mod_cgid,which starts a sufficient number instances of the CGI program to handle concurrent requests, and these programs remain running to handle further incoming requests. It is favored by the PHP developers, for example,as a preferred alternative to running mod_php in-process, delivering very similar performance.

It is a binary compatibility alternative to Apache module mod_fastcgi.

libapache2-mod-scgi
Apache module implementing the SCGI protocol
The SCGI protocol is a replacement for the Common Gateway Interface (CGI) protocol. It is a proposed standard for applications to interface with HTTP servers. It is similar to FastCGI but is designed to be easier to implement.

This package is an Apache module implementing the client side of the protocol.

libapache2-mod-speedycgi

Apache2 module to speed up perl scripts by making them persistent
SpeedyCGI is a way to run perl scripts persistently, which usually makes them run much more quickly because it avoids the overhead of starting up a new perl interpreter and compiling the perl code.

This package provides an Apache2 module so that SpeedyCGI scripts can be run without the overhead of doing a fork/exec for each request. Please note that this package only works with Apache2's prefork MPM or the ITK MPM, as it is not thread-safe.

注意:它有多年都没有更新了。

libapache2-mod-fastcgi
Apache 2 FastCGI module for long-running CGI scripts
This is a FastCGI module for the Apache 2.x web server.  FastCGI is an open standard for communicating between a web server and a long-running web application.  CGI scripts supporting FastCGI can be started as a daemon and process multiple requests without restarting.  This is particularly useful for scripts written in languages like Perl, as it saves the cost of recompiling the scripts and its loaded modules with each invocation.

2、embed
内嵌式,对应的模块有:libapache2-mod-perl2、libapache2-mod-speedycgi。

libapache2-mod-perl2
Integration of perl with the Apache2 web server
mod_perl allows the use of Perl for just about anything Apache-related, including <Perl> sections in the config files and the famous Apache::Registry module for caching compiled scripts.

It can produce anywhere from a 400% to 2000% speed increase on sites using perl scripts, and is used on many large script-based web sites.

简单的配置方法参考如下示例:

涉及的相关指令
AddHandler
Options
ScriptAlias

配置Apache以允许CGI
要让CGI程序能正常运作,必须配置Apache以允许CGI的执行,其方法有多种。

ScriptAlias
ScriptAlias指令使Apache允许执行一个特定目录中的CGI程序。当客户端请求此特定目录中的资源时,Apache假定其中文件都是CGI程序并试图运行。

ScriptAlias指令形如:
ScriptAlias /cgi-bin/ /usr/local/apache/cgi-bin/

如果Apache被安装到默认的位置,默认的配置文件httpd.conf中则会有上述配置。ScriptAlias指令定义了映射到一个特定目录的URL前缀,与Alias指令非常相似,两者一般都用于指定位于DocumentRoot目录以外的目录,其区别是ScriptAlias又多了一层含义,即其URL前缀中任何文件都被视为CGI程序。所以,上述例子会指示Apache,/cgi-bin/应该指向/usr/local/apache /cgi-bin/目录,且视为CGI程序。

举例,如果有URL为http://www.example.com/cgi-bin/test.pl的请求,Apache会试图执行/usr/local/apache/cgi-bin/test.pl文件并返回其输出。当然,这个文件必须存在而且可执行,并以特定的方法产生输出,否则Apache返回一个出错消息。

ScriptAlias目录以外的CGI
由于安全原因,CGI程序通常被限制在ScriptAlias指定的目录中,如此,管理员就可以严格地控制谁可以使用CGI程序。但如果采取了恰当的安全方法措施,则没有理由不允许其他目录中的CGI程序运行。比如,你可能希望用户在UserDir指定的宿主目录中存放页面,而他们有自己的 CGI程序,但无权存取cgi-bin目录,这样就产生了运行其他目录中CGI程序的需求。

用Options显式地允许CGI的执行
可以在主服务器配置文件中,使用Options指令显式地允许特定目录中CGI的执行:
<Directory /usr/local/apache/htdocs/somedir>
Options +ExecCGI
</Directory>

上述指令使Apache允许CGI文件的执行。另外,还必须告诉服务器哪些文件是CGI文件。下面的AddHandler指令告诉服务器所有带有cgi或pl后缀的文件是CGI程序:
AddHandler cgi-script cgi pl psp

.htaccess文件
.htaccess文件是针对目录进行配置的一种方法。Apache在提供一个资源时,会在此资源所在目录中寻找.htaccess文件,如果有,则使其中的指令生效。AllowOverride 指令决定了.htaccess文件是否有效,它指定了哪些指令可以出现在其中,或者根本不允许使用。为此,需要在主服务器配置中如此配置:
AllowOverride Options

在.htaccess文件中,需要如此配置:
Options +ExecCGI

以使Apache允许此目录中CGI程序的执行。

下面来看一些简单的配置示例:
Alias /var/www/perl
<Location /perl>
 SetHandler perl-script
 PerlResponseHandler ModPerl::Registry
 Options +ExecCGI
 PerlOptions +ParseHeaders
 PerlSendHeader On
 Order allow,deny
 Allow from all
</Location>

<Directory /var/www/dl.freeoa.net/>
 Options Indexes FollowSymLinks MultiViews
 AllowOverride None
 <Files ~ "\.(pl|psp)$">
  SetHandler perl-script
  PerlResponseHandler ModPerl::PerlRun
  Options +ExecCGI
  PerlSendHeader On
  PerlSetupEnv On
  PerlOptions +GlobalRequest
  PerlOptions +ParseHeaders
 </Files>
 Order allow,deny
 allow from all
</Directory>

可能的关键字:PerlRequire、SetHandler、PerlResponseHandler、PerlSetVar、PerlAddVar、PerlAuthenHandler、PerlAuthzHandler等。

ModPerl::PerlRun与ModPerl::Registry之间的关系

ModPerl::Registry - Run unaltered CGI scripts persistently under mod_perl
Each child process will compile the subroutine once and store it in memory. It will recompile it whenever the file (e.g. test.pl in our example) is updated on disk. Think of it as an object oriented server with each script implementing a class loaded at runtime.

The file looks much like a "normal" script, but it is compiled into a subroutine.

ModPerl::PerlRun - Run unaltered CGI scripts under mod_perl

可见前者在运行效率上要高于后者,当然是处在生产环境中,程序文件不需要经常的改动的条件下。

libapache2-mod-speedycgi
apache2 module to speed up perl scripts by making them persistent
SpeedyCGI is a way to run perl scripts persistently, which usually makes them run much more quickly because it avoids the overhead of starting up a new perl interpreter and compiling the perl code.

This package provides an Apache2 module so that SpeedyCGI scripts can be run without the overhead of doing a fork/exec for each request. Please note that this package only works with Apache2's prefork MPM or the ITK MPM, as it is not thread-safe.

stackoverflow上找到一篇关于使用各类后端处理方法的对比数据,结果如下:
cgi - 1200+ requests per minute
mod_perl - 6000+ requests per minute (ModPerl::PerlRun only)
fast_cgi - 6000+ requests per minute
mod_perl - 6000+ requests per minute (ModPerl::Registry)
servlets - 2438 requests per minute.



二、Nginx
后起之秀,劲头正盛。先进的异步机制,让它有很高并发处理能力。

对Perl的支持可有限支持的内嵌式的Nginx-Perl,更多的情况是需要后端的改良型的cgi方式(WebSocket proxying)。可参考官方wiki上提供的有关配置方法



该文章最后由 阿炯 于 2013-07-29 15:11:58 更新,目前是第 2 版。