HTTP::Async で XML-RPC
仕事で結構な数のサーバスペックを管理してるんだけど、こいつらの情報収集が結構大変。
サーバに仕込んだXMLRPCなAPIに対して、管理サーバのアプリを大量にfork->並列リクエストしてるんだけど、消費メモリが尋常じゃない。こんな無駄使いは環境に宜しくない。つか管理サーバがOOMで死む。
そんな訳で、HTTP::Asyncを使って書き直してみた。
こいつはすげーぜ!早い!軽い!省エネ!
#!/usr/bin/perl use strict; use warnings; use XMLRPC::Lite; use HTTP::Async; use HTTP::Request; use HTTP::Headers; use JSON::Syck; use YAML::Syck; my $ua = LWP::UserAgent->new; my $async = HTTP::Async->new; my $serializer = XMLRPC::Serializer->new; my $deserializer = XMLRPC::Deserializer->new; my $xml = $serializer->envelope(method => 'spec', qw/machine memory os kernel/); my $header = HTTP::Headers->new->header( "Content-Type" => 'text/xml', ); my $hosts = LoadFile(shift); my %req; for my $host (@$hosts) { my $id = $async->add( xmlrpc_req($host) ); $req{$id}->{hostname} = $host; } while ( my ($res, $id) = $async->wait_for_next_response ) { if ($res->is_success) { my $som = eval { $deserializer->deserialize($res->content) }; if ($@) { warn $@; } else { printf "%s :\t%s\n", $req{$id}->{hostname}, JSON::Syck::Dump($som->result); } } else { warn $res->status_line; } } sub xmlrpc_req { my $host = shift; return HTTP::Request->new( POST => "http://$host/rpc", $header, $xml, ); }
実際は取ってきた情報はDBにぶちこんだり、webで表示したりしとる。
ちなみに今まではこんな感じでやってた。
use Parallel::ForkManager; my $pm = Parallel::ForkManager->new($num); for my $host (@hosts) { $pm->start and next; my $som = XMLRPC::Lite ->proxy("http://$host/rpc") ->call('spec', qw/machine memory os kernel/); # hogehoge $pm->finish; } $pm->wait_all_children;
ベンチ取ってないけど、取るまでもなく全くパフォーマンスが違う。