2013-09-16 32 views
0

我有這樣的代碼(server.pl)迴應:FCGI perl腳本停止對請求

#!/usr/bin/perl 
use strict; 
use warnings; 

use FCGI; 
use POSIX qw(:signal_h); 
use Time::HiRes qw(alarm); 

my $socket = FCGI::OpenSocket(":9010", 10000); 
my $request = FCGI::Request(\*STDIN, \*STDOUT, \*STDERR, \%ENV, $socket, FCGI::FAIL_ACCEPT_ON_INTR); 

my $old_sigaction = POSIX::SigAction->new; 
my $sigaction = POSIX::SigAction->new('sig_alarm', undef, POSIX::SA_RESTART); 
POSIX::sigaction(SIGALRM, $sigaction, $old_sigaction) or die "can't sigaction: $!"; 

sub sig_alarm { 
    print "alarm " . rand() . "\n"; 
    alarm(0.01); 
} 
alarm(0.01); 
while($request->Accept() >= 0) { 
    print "Content-type: text/plain\n\n1\n"; 
} 

這是一個FCGI服務器。它監聽端口9010.它有一個線程。服務器每10毫秒在屏幕上打印一個隨機文本。

Nginx將請求傳遞給此服務器。

的nginx的配置的一部分:

location /counter/ { 

    fastcgi_pass 127.0.0.1:9010; 
    include fastcgi_params; 
} 

我開始server.pl:

$ ~/server.pl 
alarm 0.309887429307313 
alarm 0.0700285703382804 
alarm 0.524615473850769 
alarm 0.518569373615669 
... 

Server.pl是打印屏幕上的文字。

然後我推出這個命令:

/usr/local/apache/bin/ab -k -c 80 -t 300 http://127.0.0.1/counter/ 

有時server.pl停止對請求進行響應。 strace的用於server.pl顯示此:

futex(0x7f5035818e80, FUTEX_WAIT_PRIVATE, 2, NULL 

爲什麼這個happend?

+0

也許單線程有問題回答80個併發請求? – AKHolland

+0

No. $ ab -c 1 -t 300 -k http://127.0.0.1/counter/ 這是ApacheBench,版本2.3 <$ Revision:655654 $> 版權所有1996 Adam Twiss,Zeus Technology Ltd,http: /www.zeustech.net/ 授權給Apache軟件基金會,http://www.apache.org/ 標杆127.0.0.1(耐心) 完成5000個請求 完成10000個請求 完成15000個請求 ! !BLOCKING! ^ C – drlexa

+0

在相同數量的請求(15000..20000)之後它總是停止工作嗎?可能達到了極限? –

回答

0

我有完全相同的問題,但與其他信號。原因在於你使用SA_RESTART POSIX信號處理程序,甚至與perl沒有關係。這一切都取決於你在報警子中使用的呼叫。在我的情況下,它是localtime()(但通過Sys :: Syslog),它不在安全列表中,因此需要設置快速用戶鎖定(futex)。

您可以閱讀有關here

我還沒有找到一個好的解決辦法。普通的perl信號處理是可以的,但是如果沒有SA_RESTART,許多像Oracle DB庫那樣執行I/O的庫將「隨機」退出它們的調用。

如果你可以不使用SA_RESTART和POSIX處理程序,只需使用%SIG - 甚至可能在FCGI中不可能實現。