やはり必要以上にゆるいと感じたので。
リダイレクトはエラー扱いに
以下、問題と感じたところ。
$ua->is_success
は300番台でも成立する- LWP に限らず User Agent のほとんどはデフォルトではリダイレクト先まで見に行ってしまう
このままだと以下のような場合もOKになってしまう。
% lwp-request -S -mHEAD http://www.dan.co.jp/~dankogai/hijitsuzai HEAD http://www.dan.co.jp/~dankogai/hijitsuzai --> 302 Found HEAD http://blog.livedoor.jp/dankogai/ --> 200 OK Connection: close …
死活確認の場合、通常のブラウザーとしては正常なリダイレクトの追っかけはしない方がいい。
というわけで、まずはリダイレクトをエラーとして扱うようにしてみた。元記事ではmailしていたが、ここでは標準出力するにとどめている。
#!/usr/bin/perl use strict; use warnings; use LWP::UserAgent; use YAML (); use autodie; my $file = shift; my $config = YAML::LoadFile( $file || \*DATA ); my $ua = LWP::UserAgent->new( agent => 'Monita/0.01', timeout => $config->{timeout}, max_redirect => 0 ); for my $url ( @{ $config->{url} } ) { my $res = $ua->head($url); report($res) unless $res->code =~ /^2/; } sub report { my $res = shift; printf "%s => %s\n", $res->request->uri, $res->status_line; } __END__ from: xxxxxx@xxxxxx to: xxxxxx@xxxxxx timeout: 5 url: - http://www.google.co.jp/ - http://www.google.co.jp/nonexistent - http://hijitsuzai.google.co.jp/
% perl monita.pl http://www.google.co.jp/nonexistent => 404 Not Found http://hijitsuzai.google.co.jp/ => 500 Can't connect to hijitsuzai.google.co.jp:80 (Bad hostname 'hijitsuzai.google.co.jp')
出来れば非同期で
さらにもう一つの問題は、死活確認にLWPを使っていることそのものにある。LWPのアクセスは同期的なので、落ちているサイトにアクセスすると最悪でタイムアウト分待たされることになる。元記事の30秒というのは実に長いが、仮に3秒だとしても100URL監視したら300秒、5分もかかることになる。これはぜひ非同期でやりたいところだ。
というわけで、非同期化したのが以下。
#!/usr/bin/perl use strict; use warnings; use AnyEvent; use AnyEvent::HTTP; use YAML (); use autodie; my $file = shift; my $config = YAML::LoadFile( $file || \*DATA ); my $cv = AE::cv; for my $url ( @{ $config->{url} } ) { $cv->begin; http_head $url, recurse => 0, timeout => $config->{timeout}, sub { report( $_[1] ) if $_[1]->{Status} !~ /^2/; $cv->end; } } $cv->recv; sub report { my $hdr = shift; printf "%s => %d %s\n", $hdr->{URL}, $hdr->{Status}, $hdr->{Reason} } __END__ from: xxxxxx@xxxxxx to: xxxxxx@xxxxxx timeout: 5 url: - http://www.google.co.jp/ - http://www.google.co.jp/nonexistent - http://hijitsuzai.google.co.jp/
http://hijitsuzai.google.co.jp/ => 599 Device not configured http://www.google.co.jp/nonexistent => 404 Not Found
効果を確かめるために、以下のようなCGIを用意する。指定した秒数だけ待ってから返事をするだけのひどく簡単なものだ。あくまで遅延をシミュレートするだけなので、本番で使ってはいけません。
#!/usr/bin/env perl use strict; use warnings; my ($delay) = ($ENV{PATH_INFO} =~ m{^/(\d+)}); $delay ||= 1; sleep $delay; print "Content-type: text/plain;\n\n"; print "Good Morning!\n";
これに対して以下の設定でアクセスしてみた結果、こうなった。
timeout: 5 url: - http://localhost/~dankogai/test/slow.cgi/0 - http://localhost/~dankogai/test/slow.cgi/1 - http://localhost/~dankogai/test/slow.cgi/2 - http://localhost/~dankogai/test/slow.cgi/3 - http://localhost/~dankogai/test/slow.cgi/4 - http://localhost/~dankogai/test/slow.cgi/5 - http://localhost/~dankogai/test/slow.cgi/6 - http://localhost/~dankogai/test/slow.cgi/7 - http://localhost/~dankogai/test/slow.cgi/8 - http://localhost/~dankogai/test/slow.cgi/9
同期版
% /usr/bin/time perl monita.pl slow.yaml http://localhost/~dankogai/test/slow.cgi/5 => 500 read timeout http://localhost/~dankogai/test/slow.cgi/6 => 500 read timeout http://localhost/~dankogai/test/slow.cgi/7 => 500 read timeout http://localhost/~dankogai/test/slow.cgi/8 => 500 read timeout http://localhost/~dankogai/test/slow.cgi/9 => 500 read timeout 36.28 real 0.22 user 0.01 sys
非同期版
% /usr/bin/time perl monitae.pl slow.yaml http://localhost/~dankogai/test/slow.cgi/5 => 599 Operation timed out http://localhost/~dankogai/test/slow.cgi/6 => 599 Operation timed out http://localhost/~dankogai/test/slow.cgi/7 => 599 Operation timed out http://localhost/~dankogai/test/slow.cgi/8 => 599 Operation timed out http://localhost/~dankogai/test/slow.cgi/9 => 599 Operation timed out 11.19 real 0.17 user 0.01 sys
それにしてもAnyEventは楽である。fork()
で同じ事をしていた頃に比べたら天国みたいだ。
Happy Monitoring!
Dan the Man with Too Many Websites to Manage
このブログにコメントするにはログインが必要です。
さんログアウト
この記事には許可ユーザしかコメントができません。