mala氏の Studying HTTP with Perl を見ながら書いたノートの清書

  • リクエストを 5000/sec とかするときのための
  • 200/secでよければ別にLWP使ってればいいよマジで、実際便利だし。

非並列なhttpアクセス

LWP::RobotUA robots.txt見たりするので行儀が良い
URI::Fetch キャッシュとかする、インターフェースがいい
HTTP::Lite 依存モジュールなし、どこでも使えるよ
LWPx::ParanoidAgent ローカルIPは弾く、WEB魚拓的サービスに

並列なhttpアクセス

AnyEvent::HTTP 簡単
Coro::LWP コルーチン、黒魔術(なにをしてるか理解して使おう)
AnyEvent::Curl curlのオプションを覚えなくてはダメ
  • Coro::LWPはLWPをcoro使用に全て置き換えるから注意。
    • coroそのものを知りましょう

Curlって

cURLのこと、Cpan記法だからCurlだけど実際のCurlは言語。
curlっていうコマンドラインのfetch、wgetの仲間みたいなやつもある。

perlで並列処理をする場合

イベント駆動+prefork が最適解

I/O待ち
非同期
重い処理
worker
ブロッキング
forkして別プロセス

preforkは諸問題あるからイベント駆動がおすすめ
いちおう、処理時間、アクセス時間が完璧に計算出来るのであればpreforkの方がいい。

早いパーサ

HTTP::Response::Parser
  • ヘッダとかLastModifiedの速度とかbodyを分けるためのパーサ
  • 既存の重い
  • PurePerlでがんばって、XSした
  • picohttpparser(とても優秀) を使った
  • 欠点:今は不安定(関連libのせい、verupなど待ち

DNS解決が遅い

  • DNS解決に時間がかかってしまうとリクエスト投げれない
  • Squidにまかすといろいろ解決
  • Squid側でローカルIPをはじくことも出来るし(LWPx::Paranoidかわりになる)

RPC

プロトコルを作るな、httpでいい。httpは充分早いし。汎用性高いし。

テスト手法

  • タイムアウトするくらい反応遅いサーバを作ってそこにアクセス
  • あと、認証とかストリーミングとか
  • キーワード:Plack, PSGI app
タイムアウトサーバのコード
app => sub {
    my $env = shift;
    my $req = Plack::Request->new($env);
    sleep 2;
    return [
        200, [ 'Content-Type' => 'text/plain' ],
        ["Hellow World after 2 sec"] 
    ];
},
クライアント側の方
client => sub {
    my $cb  = shift;
    my $req = HTTP::Request->new(GET => "http://localhost/hello");
    my $cv  = $cb->($req, sub{}, {timeout => 1});
    my $res = $cv->recv;
    ok( !$res->is_success, "fail by timeouot" );
    is( $res->code, 500, "check status code");
    is( $res->{error}, 
        WWW::Curl::Easy->new->strerror(CURLE_OPERATION_TIMEDOUT),
       "error str"
    );
}


おわり

via http://subtech.g.hatena.ne.jp/mala/20101020