30分钟学会mod_perl

简介

在之前的文章中,我曾展示了一些公司大量部署mod_perl后的令人惊叹的Web性能报告。你可能感到惊讶,但如果你也将你的服务迁移到mod_perl,你完全可以轻松地获得类似的效果。实际上,开始使用mod_perl不需要超过30分钟的时间——这包括在性能良好的机器上编译和配置服务器,并让它运行起来。

在这篇文章中,我将一步步展示安装和配置场景,你将有机会在不阅读任何其他文档的情况下运行基本的静态编译的mod_perl设置。当然,你稍后仍然需要和需要阅读文档,但我认为你将同意我的观点,即能够在不事先了解太多新技术的情况下先尝试一下是非常酷的。

mod_perl的安装已在许多主流Unix平台上进行了测试,所以除非你有非标准系统,否则在构建基本的mod_perl服务器时不应有任何问题。

如果你是Windows用户,那么最简单的方法是使用从http://perl.apache.org/distributions.html提供的二进制包。从同一位置,你可以下载Linux RPM版本和CVS快照。然而,我总是建议从源代码构建mod_perl,并且正如你将很快看到的,这是一件很容易的事情。

安装mod_perl非常简单

让我们从安装过程开始。如果你是一个有经验的Unix用户,那么你不需要对以下命令进行解释。只需复制并粘贴它们,你就可以安装服务器。

我将使用一个%符号作为shell程序的提示符。

  % cd /usr/src
  % lwp-download http://www.apache.org/dist/httpd/apache_1.3.20.tar.gz
  % lwp-download http://perl.apache.org/dist/mod_perl-1.26.tar.gz
  % tar -zvxf apache_1.3.20.tar.gz
  % tar -zvxf mod_perl-1.26.tar.gz
  % cd mod_perl-1.26
  % perl Makefile.PL APACHE_SRC=../apache_1.3.20/src \
    DO_HTTPD=1 USE_APACI=1 EVERYTHING=1
  % make && make test && make install
  % cd ../apache_1.3.20
  % make install

这就是全部!

接下来,需要在httpd.conf(Apache配置文件)中添加几行配置,启动服务器,享受mod_perl。

如果你在上述任何步骤中遇到了问题,那么不要绝望——下一节将详细解释每个步骤。

安装mod_perl的详细步骤

如果你没有勇气尝试上一节的步骤,或者你想要在尝试之前了解更多,那么让我们深入了解安装过程的细节。如果你已经按照上一节中的简短场景成功安装了mod_perl,那么你可以跳过这一节,继续下一节。

在继续之前,我应该指出,你必须成为root用户才能将文件安装到受保护区域。如果你没有root权限,那么你可以在你的主目录下安装所有文件。我们将在未来的文章中讨论这种方法的细微差别。我还假设你已经安装了perlgcc或等效的C编译器。

我假设所有的构建都是在/home/stas/src目录中进行的。因此,我们进入这个目录。

  % cd /home/stas/src

现在,我们下载Apache和mod_perl的最新源代码分发版。如果你安装了LWP模块(也称为libwww,可从CPAN获得),那么你应该有lwp-download工具,该工具部分模仿你喜欢的浏览器,允许你从互联网上下载文件。你可以使用任何其他方法检索这些文件。只需确保将这两个文件都保存在/home/stas/src目录中,这样就会使你遵循示例安装过程更容易。当然,你可以在文件系统的任何位置安装这两个包。

  % lwp-download http://www.apache.org/dist/httpd/apache_1.3.20.tar.gz
  % lwp-download http://perl.apache.org/dist/mod_perl-1.26.tar.gz

您可以通过访问以下分发目录来确保您正在下载最新稳定的版本:http://www.apache.org/dist/httpd/http://perl.apache.org/download/index.html。如您所猜,前者是主要的Apache分发目录,后者是mod_perl的相同目录。

解压两个源文件。您必须解压并解包文件。除了其主要用于打包和解包文件的功能外,GNU tar 工具还能够在使用 -z 选项时解压由 gzip 工具压缩的文件。

  % tar -zvxf apache_1.3.20.tar.gz
  % tar -zvxf mod_perl-1.26.tar.gz

如果您有一个非GNU tar 工具,那么它很可能无法解压,因此您需要分两步进行。首先,使用以下命令解压软件包:

  % gzip -d apache_1.3.20.tar.gz
  % gzip -d mod_perl-1.26.tar.gz

然后使用以下命令解包它们:

  % tar -xvf apache_1.3.20.tar
  % tar -xvf mod_perl-1.26.tar

如果您没有可用的 targzip 工具,那么您需要安装它们或使用它们的等效工具。

现在进入mod_perl源分发目录。

  % cd mod_perl-1.26

下一步是创建 Makefile

  % perl Makefile.PL APACHE_SRC=../apache_1.3.20/src \
    DO_HTTPD=1 USE_APACI=1 EVERYTHING=1

mod_perl接受各种参数,在这个场景中,我们将使用那些将允许您使用mod_perl做几乎所有事情。一旦您对mod_perl了解更多,您将能够调整传递给 Makefile.PL 的参数列表。在未来的文章中,我将介绍所有可用的选项。

perl Makefile.PL ... 的执行将检查依赖项,并告诉您系统缺少哪些所需的软件包。如果您未安装某些Perl软件包,那么您必须在这些软件包安装完成后才能继续。它们全部可在CPAN获得,并且可以轻松下载和安装。

如果您选择使用 CPAN.pm 模块安装mod_perl,那么它将为您安装所有缺少的模块。要这样做,告诉 CPAN.pm 安装 Bundle::Apache 包。

此步骤还将执行Apache源分发目录中的 ./configure 脚本(对您来说绝对透明),该脚本准备Apache构建配置文件。如果您需要向Apache的 ./configure 脚本传递参数,则将它们作为选项传递给 perl Makefile.PL ...。在未来的文章中,我们将讨论所有可用的选项。

现在您应该使用 make 工具构建 httpd 可执行文件。

  % make

此命令准备mod_perl扩展文件,将它们安装在Apache源树中,并通过编译所有必需的文件构建 httpd 可执行文件(即Web服务器本身)。在 make 过程完成后,您将返回到mod_perl源分发目录。

make test 在刚构建的 httpd 可执行文件上执行各种mod_perl测试。

  % make test

此命令在非标准端口(8529)上启动服务器,并测试构建的服务器所有部分是否正确运行。如果出现问题,则进程将向您报告。

make install 通过安装mod_perl运行所需的所有Perl文件以及服务器文档(man页面)来完成mod_perl的安装过程。

  % make install

您可以使用以下命令的连接方式

  % make && make test && make install

这简化了安装过程,因为您不必等待每个命令完成才能开始下一个命令。当第一次为mod_perl安装时,最好分步骤进行。

如果您选择一站式方法,那么您应该知道如果 make 失败,则 make testmake install 都不会执行。如果 make test 失败,则 make install 也不会执行。

最后,切换到Apache源分发目录,运行 make install 以创建Apache目录树并安装Apache头文件(*.h)、默认配置文件(*.conf)、httpd 可执行文件和一些其他程序。

  % cd ../apache_1.3.20
  % make install

请注意,与普通Apache安装一样,此过程不会覆盖先前安装留下的任何配置文件。在安装之前,您不需要备份之前工作的配置文件。

make install过程完成后,它将告诉您如何启动一个新建的Web服务器(用于控制服务器的apachectl实用程序的路径)以及安装的配置文件所在的位置。请记住,或者更好的是,写下这两个路径,因为您将需要这些信息。在我的机器上,两个重要的路径是

  /usr/local/apache/bin/apachectl
  /usr/local/apache/conf/httpd.conf

到目前为止,我们已经完成了启用mod_perl的Apache的构建和安装。下一步是配置httpd.conf,编写一个小测试脚本,启动服务器并检查测试脚本是否正常工作。

配置和启动mod_perl服务器

首先,我们想确保我们的Apache构建正确,并且可以使用它来服务纯HTML文件。为什么要这样做?为了最小化可能的问题制造者数量,如果我们发现mod_perl不能工作。在您知道Apache可以服务HTML文件后,您就无需再担心它了。如果mod_perl出现问题,您已排除了httpd二进制文件或基本配置损坏的可能性,您知道您可以绑定到已配置服务器监听的端口号,并且您测试的浏览器是正常的。再次提醒,当您第一次安装mod_perl时,应遵循这些指南。

像往常一样配置Apache。在httpd.conf文件中设置PortUserGroupErrorLog和其他指令(记得我要求您在上一节末尾记住该文件的存放位置?)。使用默认值,除非您必须自定义。您需要自定义的值包括ServerNamePortUserGroupServerAdminDocumentRoot和其他几个。您将发现每个指令之前都有有用的提示。如有疑问,请遵循它们。

编辑完配置文件后,是时候启动服务器了。启动和停止服务器的一种方法是通过使用apachectl实用程序。您使用以下命令启动服务器

  % /usr/local/apache/bin/apachectl start

然后使用以下命令停止它

  % /usr/local/apache/bin/apachectl stop

请注意,如果服务器要监听端口号80或另一个特权端口(<1024)时,您必须以root用户身份启动服务器。

启动服务器后,检查error_log文件(默认位置为/usr/local/apache/logs/error_log),确认服务器确实已启动。不要依赖apachectl报告的状态。您应该看到类似以下内容

  [Thu Jun 22 17:14:07 2000] [notice] Apache/1.3.20 (Unix)
  mod_perl/1.26 configured -- resuming normal operations

现在,将您的浏览器指向配置了ServerName指令的http://localhost/http://your.server.name/。如果您的Port指令的值不是80,则在服务器名后应用此端口号。如果您使用的是端口号8080,则使用http://localhost:8080/http://your.server.name:8080/测试服务器。您应该看到著名的“``It worked”页面,这是在Apache源树中由make install安装的index.html文件。如果您没有看到此页面,则表示有问题,您应检查error_log文件的内容。您可以通过在httpd.conf中的ErrorLog指令中查找来找到错误日志文件的路径。

如果一切按预期进行,则关闭服务器,用您喜欢的编辑器打开httpd.conf,并将光标移到文件末尾,我们将在此处添加mod_perl配置指令(当然,您可以将它们放在文件的任何位置)。

假设您将所有应由启用mod_perl的服务器执行的脚本放在/home/httpd/perl/目录中,请添加以下配置指令:

  Alias /perl/ /home/httpd/perl/

  PerlModule Apache::Registry
  <Location /perl>
    SetHandler perl-script
    PerlHandler Apache::Registry
    Options ExecCGI
    PerlSendHeader On
    allow from all
  </Location>

保存修改后的文件。

此配置会导致每个以/perl开头的URI都由Apache mod_perl模块处理。它将使用来自Perl模块Apache::Registry的处理程序。

准备脚本目录

现在创建一个不存在的/home/httpd/perl/目录。为了您和Apache能够读取、写入和执行文件,我们必须设置正确的权限。您可以简单地这样做:

  % chmod 0777  /home/httpd/perl

这非常非常不安全,您不应该在生产机器上采用这种方法。如果您只是想尝试事物并且想尽可能少地遇到障碍,这足够了。一旦您了解了事物是如何工作的,您应该调整Apache所服务的文件的权限。在未来文章中,我们将讨论设置适当的文件权限。

Apache::Registry脚本“mod_perl规则”

如您所知,mod_perl允许您重用以前在mod_cgi下使用的Perl编写的CGI脚本。因此,我们的第一个测试脚本可以非常简单:

  mod_perl_rules1.pl
  ------------------
  print "Content-type: text/plain\r\n\r\n";
  print "mod_perl rules!\n";

将此脚本保存到/home/httpd/perl/mod_perl_rules1.pl文件中。注意,mod_perl不需要shebang行,但您可以保留它。所以下面的脚本也可以使用:

  mod_perl_rules1.pl
  ------------------
  #!/usr/bin/perl
  print "Content-type: text/plain\r\n\r\n";
  print "mod_perl rules!\n";

当然,您可以使用Apache Perl API编写相同的脚本

  mod_perl_rules2.pl
  ------------------
  my $r = shift;
  $r->send_http_header('text/plain');
  $r->print("mod_perl rules!\n");

将此脚本保存到/home/httpd/perl/mod_perl_rules2.pl文件中。

现在使这两个脚本对服务器可执行和可读。请记住,当您从shell执行脚本时,它们是由您登录的用户名执行的。当您通过发出请求来运行脚本时,Apache需要能够读取和执行它们。因此,我们将脚本设置为对每个人可读和可执行

  % chmod 0755   /home/httpd/perl/mod_perl_rules1.pl \
                 /home/httpd/perl/mod_perl_rules2.pl

如果您不希望其他用户能够读取您的脚本,那么您应该将自己添加到Web服务器运行的组名(由Group指令定义)中,然后使脚本属于该组并调整权限。例如,在我的机器上,我在httpd组下运行服务器,我是唯一一个在该组中的人,所以我可以这样做:

  % chown stas.httpd /home/httpd/perl/mod_perl_rules1.pl \
                 /home/httpd/perl/mod_perl_rules2.pl

  % chmod 0750   /home/httpd/perl/mod_perl_rules1.pl \
                 /home/httpd/perl/mod_perl_rules2.pl

第一个命令使文件属于httpd组,第二个设置适当的执行和读取权限。

这是安全的,假设您为您的服务器有一个专用的组名。

此外,请记住,所有指向脚本的目录都应该由服务器可读和可执行。

您可以从命令行测试mod_perl_rules1.pl,因为本质上它是一个常规的Perl脚本。

  % perl /home/httpd/perl/mod_perl_rules1.pl

您应该看到以下输出:

  mod_perl rules!

您无法通过从命令行执行它来测试第二个脚本,因为它使用了仅在mod_perl服务器内部运行的mod_perl API。

确保服务器正在运行,并使用您喜欢的浏览器发出这些请求

  http://localhost/perl/mod_perl_rules1.pl
  http://localhost/perl/mod_perl_rules2.pl

在这两种情况下,您都会在以下响应中看到:

  mod_perl rules!

如果您看到了它——恭喜!您有一个工作的mod_perl服务器。

如果您使用的是8080端口而不是80,那么您应该在URL中使用此数字

  http://localhost:8080/perl/mod_perl_rules1.pl
  http://localhost:8080/perl/mod_perl_rules2.pl

localhost方法仅在浏览器在运行服务器的同一台机器上时才有效。如果不是,则使用实际的服务器名称进行此测试。例如

  http://your.server.name/perl/mod_perl_rules1.pl

如果出现任何问题,请参阅error_log文件以获取错误报告。

现在是将您的CGI脚本从/somewhere/cgi-bin目录移到/home/httpd/perl/目录,并看到它们在新配置的基础URL(/perl/)请求时运行得更快。如果您以前是通过/cgi-bin/test.pl访问脚本的,那么现在将通过/perl/test.pl访问它。

您的一些脚本可能无法立即工作,需要一些微调甚至部分重写才能与 mod_perl 正确配合。如果您不进行草率编程,那么脚本将无需修改即可运行。

如果您的脚本出现问题,一个好的方法是将其中的 Apache::Registry 替换为 Apache::PerlRun,因为它可以执行编写得非常糟糕的脚本。请在 httpd.conf 中放置以下配置指令,并重新启动服务器

  PerlModule Apache::PerlRun
  <Location /perl>
    SetHandler perl-script
    PerlHandler Apache::PerlRun
    Options ExecCGI
    PerlSendHeader On
    allow from all
  </Location>

现在您的脚本应该可以工作了,除非它们包含 mod_perl 不接受的内容。我们将在未来的文章中讨论这些细微差别。

“mod_perl 规则” Apache Perl 模块

mod_perl 是关于运行脚本和处理器。虽然我已经开始使用脚本介绍 mod_perl,因为如果您之前编写过 CGI 脚本,这将更容易,但 mod_perl 的更高级使用是编写处理器。但不要担心。正如您一会儿将看到的,编写处理器几乎和编写脚本一样简单。

要创建一个 mod_perl 处理器模块,我只需将用于脚本的代码包装在一个 handler 子例程中,在子例程成功完成后向服务器返回状态语句,并在代码顶部添加一个包声明。

就像脚本一样,您可以使用您可能熟悉的 CGI API

  ModPerl/Rules1.pm
  ----------------
  package ModPerl::Rules1;
  use Apache::Constants qw(:common);

  sub handler{
    print "Content-type: text/plain\r\n\r\n";
    print "mod_perl rules!\n";
    return OK;
  }
  1; # satisfy require()

或者允许您通过提供在常规 Perl 下不可用的 API 更亲密地与 Apache 核心交互的 Apache Perl API。当然,在我的简单示例中,使用任何一种方法都可以,但当你需要使用 API 时,应使用此版本的代码。

  ModPerl/Rules2.pm
  ----------------
  package ModPerl::Rules2;
  use Apache::Constants qw(:common);

  sub handler{
    my $r = shift;
    $r->send_http_header('text/plain');
    print "mod_perl rules!\n";
    return OK;
  }
  1; # satisfy require()

@INC 目录中的一个目录下创建一个名为 ModPerl 的目录(例如 /usr/lib/perl5/site_perl/5.005),并将 Rules1.pmRules2.pm 放入其中,这些文件应包含上面示例中的代码。

要找出 @INC 目录是什么,执行

  % perl -le 'print join "\n", @INC'

在我的机器上,它报告

  /usr/lib/perl5/5.6.1/i386-linux
  /usr/lib/perl5/5.6.1
  /usr/lib/perl5/site_perl/5.6.1/i386-linux
  /usr/lib/perl5/site_perl/5.6.1
  /usr/lib/perl5/site_perl
  .

现在将以下片段添加到 httpd.conf 中,以配置 mod_perl 在请求 mod_perl_rules1 时执行 ModPerl::Rules::handler 子例程

  PerlModule ModPerl::Rules1
  <Location /mod_perl_rules1>
    SetHandler perl-script
    PerlHandler ModPerl::Rules1
  </Location>

现在您可以发出一个请求到

  http://localhost/mod_perl_rules1

并且就像我们的 mod_perl_rules.pl 脚本一样,您将看到

  mod_perl rules!

作为响应。

要测试第二个模块 <ModPerl::Rules2>,添加相同的配置,将所有 1 替换为 2

  PerlModule ModPerl::Rules2
  <Location /mod_perl_rules2>
    SetHandler perl-script
    PerlHandler ModPerl::Rules2
  </Location>

要测试,请使用 URI

  http://localhost/mod_perl_rules2

关于 mod_perl 我需要知道这些吗?

显然,您接下来会问的问题是:“这是关于 mod_perl 我需要知道的所有吗?”。

答案是:“是,也不是”。

“是”的部分

  • 就像 Perl 一样,您只需要对 mod_perl 有很少的了解就能做真正酷的事情。所展示的设置允许您以更快的速度运行您的访客计数器和留言簿,并让您的朋友惊讶,通常无需更改代码的任何一行。

“不是”的部分

  • 将留言簿的响应时间提高 50 倍是很好的,但当一个包含数千个并发用户的重型服务部署时,考虑到类似 Web 服务之间的高级别竞争,几毫秒的延迟可能会让您失去一个客户,可能还有很多。

    当然,当您测试单个脚本并且您是唯一用户时,您并不真正关心从响应时间中挤出另一毫秒,但当这些毫秒在生产站点上累积,有数百个用户同时向您网站上的各种脚本生成请求时,这成为一个真正的问题。现在的用户并不仁慈——如果还有另一个提供相同服务但速度略快一点的网站,那么他们很可能会去那里。

    在未加载的机器上测试脚本可能会产生误导,一切看起来都如此完美。但当你把它们转移到生产机器上时,它们的性能并不像在开发环境中那样好。很多时候,你只是因为繁忙的服务而耗尽内存。你需要学习如何优化代码以使用更少的内存,以及如何实现内存共享。

    调试是人们不愿谈论的话题,因为这个过程可能会很繁琐。如果你认为自己是一名Web程序员,那么学习如何使调试过程更加简单和高效是必不可少的。这项任务在调试CGI脚本时尤其不是那么直接,而当使用mod_perl时,问题变得更加复杂——除非你了解如何操作,否则它突然变得容易。

    参考文献

    Apache网站URL: http://www.apache.org/

    mod_perl网站URL: http://perl.apache.org/

    CPAN是综合Perl归档网络。主站URL是 http://cpan.org/。CPAN在全球超过100个站点进行了镜像。(http://cpan.org/SITES.html)

    当与数据库一起使用时,mod_perl有许多在mod_cgi下不可用的功能。其中最重要的包括持久连接。

    你必须知道如何让你的服务不间断运行,并且能够在出现问题时快速恢复。

    最后,最重要的是Apache-Perl API,它允许你对收到的请求做任何事情,甚至干预请求处理的每个阶段。这给了你极大的灵活性,并允许你创建用普通的mod_cgi无法想象的东西。

关于mod_perl和Web编程还有许多其他东西需要学习。在未来文章中,我将详细讨论所有这些问题。

致谢

非常感谢Eric Cholet对本文章的审阅。

标签

反馈

这篇文章有问题吗?请通过在GitHub上打开问题或拉取请求来帮助我们。