1

我无法让我的 Perl 脚本在服务器上稳定运行。这是问题所在。

当脚本每秒访问超过 5 次时,服务器会冻结。一段时间后,服务器永远挂起。SSH 没有响应,我必须重新启动服务器。

我将 Apache 与mod_perl.

该脚本托管在 Ubuntu 下的虚拟专用服务器上。我通过 SSH 操作它。这些是服务器参数 CPU:400 MHz RAM:256 MB

脚本的最大执行时间为 200 毫秒。

我使用“top”实用程序监控了服务器负载。它没有显示任何问题,这是每秒加载 5 个脚本期间的 CPU 统计信息:

中央处理器:12.1%us、0.6%sy、0.0%ni、0.0%id、0.0%wa、0.0%hi、0.0%si、87.2%st

我必须有哪些选项才能使脚本正常工作?

这是ps aux | fgrep perl加载时的结果:

ps辅助| fgrep perl
www-数据 2925 0.3 6.5 45520 17064 ? R 17:00 0:01 /var/www/perl/loa -k 开始
www-数据 2926 0.2 6.5 45520 17068 ? R 17:00 0:01 /var/www/perl/loa -k 开始
www-数据 2927 0.4 6.5 45676 17060 ? R 17:00 0:01 /var/www/perl/loa -k 开始
www-数据 2928 0.3 6.5 45676 17060 ? R 17:00 0:01 /var/www/perl/loa -k 开始
www-数据 2929 0.2 6.5 45676 17060 ? R 17:00 0:01 /var/www/perl/loa -k 开始
www-数据 2931 0.4 6.5 45740 17076 ? R 17:00 0:01 /var/www/perl/loa -k 开始
根 2968 0.0 0.2 3196 656 pts/0 R+ 17:06 0:00 fgrep perl

更新

我找到了瓶颈。我在代码中多次使用 DateTime 模块。以下 DateTime 模块方法似乎很慢。

  • 新的()
  • 现在()
  • 放(...)
  • delta_ms(...)

我将用快速类似物代替它们。

另一个担忧。mod_perl 实例占用大量内存。我不知道为什么。我试图运行一个不导入任何模块的简单 perl 脚本。我在apache重新启动后运行它。该脚本占用 37M 内存。为什么会这样?你知道如何强制 mod_perl 不使用额外的内存吗?

没有 mod_perl 支持的常规 perl 脚本占用 3-5M 内存。

伙计们,谢谢你们这么多的帮助,我没想到会有这么好的反应!

更新 2

我又发现了一个事实。我创建了一个简单的 perl 脚本,它只等待 5 秒。

#!/usr/bin/perl
use CGI;

my $query= new CGI;
my $content = "5 second delay...\n";

$query->header(
    '-Content-type' => "text/plain",
    '-Content-Length' => length($content)
);

print $content;

sleep(5);

然后我同时生成许多这些脚本。顶级实用程序中的隐身时间 (st) 从 0% 上升到 80% 并保持高位,直到脚本完成。

这个负载从何而来?

另外,正如我已经提到的,每个 perl 实例占用 36M 内存。

4

4 回答 4

5

您的数字top似乎表明您的 VM 之外的其他进程正在限制您的 CPU,请注意最后一个数字87.2%st,这表明您的虚拟机管理程序将大约 87% 的 CPU 时间分配给您的 VM 之外的任务,即使您的VM 有它想运行的东西。这是否与您的问题有关很难说。

除了按照unwind的建议升级服务器之外,使用zoul建议的持久进程环境,您的进程可能根本不受 CPU 限制,而是受 IO 限制,例如网络或磁盘访问,或者内存绑定。如果没有关于脚本在调用时实际执行的操作的更多详细信息,很难说。

编辑:您更新的关于您的内存使用信息的问题正在揭示,因为您的每个进程都希望自己拥有 45M 的 ram,并且共享 17M 更多。仅运行 5 或 6 个进程,您就超过了可用的 RAM 量。对于一个普通的 Perl 脚本来说,这是一个很好的内存量,它有什么用呢?

于 2009-10-09T13:09:10.523 回答
3

那不是一个非常大的服务器。会不会只是简单地产生了让它下跪的 Perl 解释器?每秒五次加载 perl(我很高兴地假设它超过 1 MB)可能要求太多。

当然,它应该被缓存,但它仍然需要初始化才能执行。

于 2009-10-09T12:46:50.890 回答
1

虽然按照今天的标准,服务器的规格并不令人印象深刻,但我在类似的硬件上同时运行了相当复杂的东西。但是,我使用了一个非常准系统,只运行 FreeBSD 所需的配置。(类似于您可以使用 ArchLinux 实现的目标)。我怀疑您没有进行很多自定义配置,并且接受了 Ubuntu 默认设置,这对于这些规范来说可能太重了。

目前,我正在使用 Linode 360​​,性能还不错。

现在,所有这些都是为了说明一个显而易见的事实:我们需要您尚未与我们分享的信息。Web 服务器配置、脚本 + 解释器的内存占用、打开的文件数量等。尝试提供仍然存在问题的最小脚本或提供更多信息。

更新:现在我看到您正在使用mod_perl:1)您是否确保脚本所需的所有库都在服务器启动时预加载?variable won't stay shared2)您是否在日志中收到任何消息?3) 你读过mod_perl Performance吗?(第 10 章:共享内存可能特别相关)。

通常,您应该在 Apache 服务器启动时预加载公共库。作为一个非常简单的经验法则,共享的东西越多,您从服务器中获得的东西就越多。请参阅实用 mod_perl中的启动文件

另外,我认为每台服务器 35MB 有点多。如果您从 Apache 配置中删除不需要的模块,我认为您可以减少它。然而,即使你不能说所有的 35MB 都是共享的,再加上最大的子进程是 50MB,你一次应该能够容纳大约 20 个客户端。

我刚刚注意到您正在测试的脚本。真的,尝试CGI在服务器启动时通过以下行添加到您的预加载startup.pl

use strict;
use warnings;

use CGI();

其次,将该脚本更改为

#!/usr/bin/perl

use strict;
use warnings;
use CGI ();

$| = 1;

handle_request();

sub handle_request {
    my $cgi = CGI->new;

    my $content = "5 second delay...\n";

    print $cgi->header('text/plain'), $content;

    sleep(5);
}

请注意,您从未在原始脚本中发送标头(我也讨厌调用CGI实例$query,所以我也冒昧地更改了它)。另请参阅Perl 参考

之后报告内存使用情况。

最后,你为什么睡5秒?AFAIK,Apache 脚本的默认超时时间是 3 秒。

于 2009-10-09T13:11:15.950 回答
0

脚本使用什么样的界面?如果您可以避免perl一次又一次地运行可执行文件,例如使用FastCGI ,您肯定会获得更好的性能。

于 2009-10-09T12:50:26.717 回答