我不能让我的Perl脚本在服务器上运行稳定。 这是问题所在。
当脚本每秒访问次数超过5次时,服务器会冻结。 一段时间后,服务器永远挂起。 SSH没有响应,我必须重新启动服务器。
我正在使用Apache mod_perl
。
该脚本托管在Ubuntu下的Virtual Dedicated Server上。 我是通过SSH操作的。 这些是服务器参数 CPU:400 MHz RAM:256 MB
脚本的最长执行时间是200毫秒。
我已使用“top”实用程序监控服务器负载。 它不会显示任何问题,这是每秒加载5个脚本时的CPU统计信息:
Cpu(s): 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 aux | fgrep perl www-data 2925 0.3 6.5 45520 17064 ? R 17:00 0:01 /var/www/perl/loa -k start www-data 2926 0.2 6.5 45520 17068 ? R 17:00 0:01 /var/www/perl/loa -k start www-data 2927 0.4 6.5 45676 17060 ? R 17:00 0:01 /var/www/perl/loa -k start www-data 2928 0.3 6.5 45676 17060 ? R 17:00 0:01 /var/www/perl/loa -k start www-data 2929 0.2 6.5 45676 17060 ? R 17:00 0:01 /var/www/perl/loa -k start www-data 2931 0.4 6.5 45740 17076 ? R 17:00 0:01 /var/www/perl/loa -k start root 2968 0.0 0.2 3196 656 pts/0 R+ 17:06 0:00 fgrep perl
更新
我找到了瓶颈。 我一直在代码周围多次使用DateTime模块。 以下DateTime模块方法似乎非常慢。
我打算用快速类比替代它们。
另一个问题。 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);
然后我同时产生了许多这些脚本。 top工具中的隐藏时间(st)从0%上升到80%并保持高位,直到脚本完成。
这种负荷来自哪里?
另外,正如我已经提到的,每个perl实例需要36M的内存。
答案 0 :(得分:5)
来自top
的数字似乎表明您的VM外部的其他进程会限制您的CPU,请注意最后一个数字, 87.2%st ,这表示大约87%的CPU即使您的VM有想要运行的东西,您的虚拟机管理程序也会为VM外部的任务分配时间。这是否与您的问题有关很难说。
除了unwind所建议的升级服务器之外,使用zoul建议的持久进程环境,您的进程可能根本不受CPU限制,而是IO绑定,例如至于网络或磁盘访问,或内存限制。如果没有更多关于脚本在调用时实际执行的操作的细节,很难说。
编辑:您的内存使用情况信息的更新问题很明显,因为您的每个进程都需要45M的内存,并且共享17M以上。只运行5或6个进程,就超出了可用的RAM量。这是一个很好的内存供香草Perl脚本使用,它用它做什么?
答案 1 :(得分:3)
这不是一个非常大的服务器。它可以简单地产生让它跪下的Perl解释器吗?加载perl(我高兴地假设超过1 MB)每秒五次可能会要求太多。
当然,它应该被缓存,但在执行之前仍然需要初始化。
答案 2 :(得分:1)
虽然按照今天的标准,服务器的规格并不令人印象深刻,但我在类似的硬件上同时运行了相当复杂的东西。但是,我使用了非常准确的运行,只运行FreeBSD所需的配置。 (类似于使用ArchLinux可以实现的)。我怀疑你没有做很多自定义配置,并且接受了Ubuntu默认值,这些默认值对于那些规格来说可能太重了。
目前,我正在使用Linode 360,性能很好。
现在,所有这一切都是为了表明显而易见的:我们需要您没有与我们分享的信息。 Web服务器配置,脚本+解释器的内存占用,打开的文件数等等。要么尝试提供仍然存在问题的最小脚本,要么提供更多信息。
更新:现在我看到您正在使用mod_perl
:1)您确定脚本所需的所有库都是在服务器启动时预加载的吗? 2)您是否在日志中收到任何variable won't stay shared
条消息? 3)你读过mod_perl Performance吗? (Chapter 10: Sharing Memory可能特别相关)。
通常,您应该在Apache服务器的开头预加载公共库。作为一个非常简单的经验法则,共享的内容越多,您从服务器中获得的内容就越多。请参阅Startup File中的Practical 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 Reference。
在此之后报告内存使用情况。
最后,你为什么要睡5秒? AFAIK,Apache默认的脚本超时时间为3秒。
答案 3 :(得分:0)
脚本使用什么样的界面?如果您可以避免一次又一次地运行perl
可执行文件,例如使用FastCGI,您肯定会获得更好的性能。