我正在尝试向不可靠的服务器实现请求.请求是一个很好的,但我的perl脚本不能100%成功完成.问题是服务器偶尔会死锁(我们试图找出原因)并且请求永远不会成功.由于服务器认为它是活动的,它会使套接字连接保持打开状态,因此LWP :: UserAgent的超时值对我们来说没有任何好处.对请求强制执行绝对超时的最佳方法是什么?
仅供参考,这不是DNS问题.死锁与大量同时访问Postgres数据库的更新有关.出于测试目的,我们基本上在服务器响应处理程序中放置了while(1){}行.
目前,代码如下所示:
my $ua = LWP::UserAgent->new; ua->timeout(5); $ua->cookie_jar({}); my $req = HTTP::Request->new(POST => "http://$host:$port/auth/login"); $req->content_type('application/x-www-form-urlencoded'); $req->content("login[user]=$username&login[password]=$password"); # This line never returns $res = $ua->request($req);
我尝试使用信号来触发超时,但这似乎不起作用.
eval { local $SIG{ALRM} = sub { die "alarm\n" }; alarm(1); $res = $ua->request($req); alarm(0); }; # This never runs print "here\n";
我将要使用的最终答案是有人离线提出的,但我会在这里提到它.出于某种原因,SigAction有效,而$ SIG(ALRM)却没有.仍然不确定为什么,但这已经过测试可行.这是两个工作版本:
# Takes a LWP::UserAgent, and a HTTP::Request, returns a HTTP::Request sub ua_request_with_timeout { my $ua = $_[0]; my $req = $_[1]; # Get whatever timeout is set for LWP and use that to # enforce a maximum timeout per request in case of server # deadlock. (This has happened.) use Sys::SigAction qw( timeout_call ); our $res = undef; if( timeout_call( 5, sub {$res = $ua->request($req);}) ) { return HTTP::Response->new( 408 ); #408 is the HTTP timeout } else { return $res; } } sub ua_request_with_timeout2 { print "ua_request_with_timeout\n"; my $ua = $_[0]; my $req = $_[1]; # Get whatever timeout is set for LWP and use that to # enforce a maximum timeout per request in case of server # deadlock. (This has happened.) my $timeout_for_client = $ua->timeout() - 2; our $socket_has_timedout = 0; use POSIX; sigaction SIGALRM, new POSIX::SigAction( sub { $socket_has_timedout = 1; die "alarm timeout"; } ) or die "Error setting SIGALRM handler: $!\n"; my $res = undef; eval { alarm ($timeout_for_client); $res = $ua->request($req); alarm(0); }; if ( $socket_has_timedout ) { return HTTP::Response->new( 408 ); #408 is the HTTP timeout } else { return $res; } }
Stephen Deke.. 12
您可以尝试LWPx :: ParanoidAgent,LWP :: UserAgent的子类,它对如何与远程Web服务器交互更加谨慎.
除此之外,它还允许您指定全局超时.它由Brad Fitzpatrick开发,作为LiveJournal项目的一部分.
您可以尝试LWPx :: ParanoidAgent,LWP :: UserAgent的子类,它对如何与远程Web服务器交互更加谨慎.
除此之外,它还允许您指定全局超时.它由Brad Fitzpatrick开发,作为LiveJournal项目的一部分.