Perl 如何进行故障转移

Perl 如何进行故障转移,perl,lwp-useragent,Perl,Lwp Useragent,如果我使用wget从geonames.org服务器检索某些内容,它会报告两个IP地址,第一个IP地址失败,但它从第二个IP地址获取: Resolving ws.geonames.org (ws.geonames.org)... 5.9.41.208, 176.9.107.169 Connecting to ws.geonames.org (ws.geonames.org)|5.9.41.208|:80... failed: Connection refused. Connecting to ws

如果我使用
wget
从geonames.org服务器检索某些内容,它会报告两个IP地址,第一个IP地址失败,但它从第二个IP地址获取:

Resolving ws.geonames.org (ws.geonames.org)... 5.9.41.208, 176.9.107.169
Connecting to ws.geonames.org (ws.geonames.org)|5.9.41.208|:80... failed: Connection refused.
Connecting to ws.geonames.org (ws.geonames.org)|176.9.107.169|:80... connected.
HTTP request sent, awaiting response... 200 OK
但不幸的是,我必须使用LWP::UserAgent和HTTP::Request通过perl访问它。如果第一个IP失败,我如何让他们尝试第二个IP

    my $ua = LWP::UserAgent->new;
my $req = HTTP::Request->new(
    GET =>
      "http://ws.geonames.org/countrySubdivision?lat=$lat&lng=$long&radius=$radius&username=xyzzy");

my $res = $ua->request($req);

您可以自己做:在
Net::DNS::Resolver
的帮助下获取所有IP地址,然后尝试所有IP地址,直到获得成功响应。请注意,如果服务器使用的是基于名称的虚拟主机,则在使用IP地址时必须自己提供“主机”头

类似于下面几行的东西可能会起作用。可能还有一个CPAN模块,我没有检查:

use Net::DNS;
use LWP::UserAgent;

my @addrs;
{
    my $res   = Net::DNS::Resolver->new;
    my $query = $res->search("ws.geonames.org");
    if ($query) {
        for my $rr ($query->answer) {
            if ($rr->type eq "A") {
                push @addrs, $rr->address;
            }
        }
    } else {
        die "DNS query failed: ", $res->errorstring, "\n";
    }
}

my $ua = LWP::UserAgent->new;

my $res;
for my $addr (@addrs) {
    $res = $ua->get("http://$addr/countrySubdivision?lat=$lat&lng=$long&radius=$radius&username=xyzzy", Host => 'ws.geonames.org');
    last if $res->is_success;
}

Slaven的解决方案可以,除非IP地址无法直接访问。 在这种情况下,以下方法适用于我:

local @LWP::Protocol::http::EXTRA_SOCK_OPTS = (
                                           PeerAddr   => 'my_hostname',
                                           MultiHomed => 1,
                                          );
my $response = $ua->post('https://my_hostname/...', ...);

对不起,在写评论之前确实没有看到。因此,我删除了该注释,因为它根本不适用。好的,我也删除了我的回复:-)您确定这不是LWP::UserAgent的默认行为吗?今天在深入研究LWP::UserAgent代码之后,似乎当流套接字在IO::socket::INET::configure()中深入连接时,它将尝试为给定主机名返回的所有IP地址,并将解决它可以连接到的第一个IP。@RobWells,问题是这两个IP之间存在差异“可以打开套接字”和“在超时时间内获取有效的HTTP响应”“
wget
如果第二部分失败,将继续下一部分,但是
LWP::UserAgent
没有。cheers@Paul。我已经看到,您必须显式启用MultiHome选项,以使该行为在多个IP之间循环。它埋在PerlOO->SUPER::foo的泥潭中,所以追踪它很“有趣”!(:设置起来似乎不容易:这也意味着它可能不符合我的要求。我必须尝试一下。