Tôi đang cố triển khai yêu cầu tới một máy chủ không đáng tin cậy. Yêu cầu là một điều tuyệt vời để có, nhưng không yêu cầu 100% cho tập lệnh perl của tôi để hoàn tất thành công. Vấn đề là máy chủ đôi khi sẽ bế tắc (chúng tôi đang cố gắng tìm ra lý do) và yêu cầu sẽ không bao giờ thành công. Kể từ khi máy chủ nghĩ rằng nó là sống, nó giữ kết nối socket mở do đó giá trị thời gian chờ LWP :: UserAgent của chúng tôi không có gì tốt-bao giờ hết. Cách tốt nhất để thực thi thời gian chờ tuyệt đối trên yêu cầu là gì?Đúng thời gian chờ trên LWP :: Phương thức yêu cầu UserAgent
FYI, đây không phải là sự cố DNS. Bế tắc có liên quan đến một số lượng lớn các bản cập nhật đang tấn công cơ sở dữ liệu Postgres của chúng tôi cùng một lúc. Với mục đích thử nghiệm, về cơ bản chúng tôi đã đặt một dòng (1) {} trong trình xử lý phản hồi của máy chủ.
Hiện nay, các mã trông giống như vậy:
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);
Tôi đã thử sử dụng tín hiệu để kích hoạt một thời gian chờ, nhưng điều đó dường như không làm việc.
eval {
local $SIG{ALRM} = sub { die "alarm\n" };
alarm(1);
$res = $ua->request($req);
alarm(0);
};
# This never runs
print "here\n";
Câu trả lời cuối cùng tôi sẽ sử dụng được đề xuất bởi một người nào đó ngoại tuyến, nhưng tôi sẽ đề cập đến nó ở đây. Vì một số lý do, SigAction hoạt động trong khi $ SIG (ALRM) thì không. Vẫn không chắc chắn tại sao, nhưng điều này đã được thử nghiệm để hoạt động. Dưới đây là hai phiên bản đang hoạt động:
# 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;
}
}
Có thể trùng lặp [Làm cách nào để thực thi thời gian chờ định trước trong perl?] (Http://stackoverflow.com/questions/15899855/how-to-enforce-a - TimeTime-in-perl) – sixtyfootersdude