Danga::Socketの非同期処理の仕組みとPerlbalで非同期処理するプラグインを書く方法
Upcoming SlideShare
Loading in...5
×
 

Danga::Socketの非同期処理の仕組みとPerlbalで非同期処理するプラグインを書く方法

on

  • 4,652 views

 

Statistics

Views

Total Views
4,652
Views on SlideShare
4,524
Embed Views
128

Actions

Likes
2
Downloads
6
Comments
0

6 Embeds 128

http://coderwall.com 91
http://hiroki.jp 25
http://www.slideshare.net 8
http://test.hiroki.jp 2
http://webcache.googleusercontent.com 1
http://www.slideee.com 1

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Danga::Socketの非同期処理の仕組みとPerlbalで非同期処理するプラグインを書く方法 Danga::Socketの非同期処理の仕組みとPerlbalで非同期処理するプラグインを書く方法 Presentation Transcript

  • YAPC::Asia 2009 Tokyo 2009/9/10 宮下 剛輔
  • 自己紹介
    • 宮下 剛輔( mizzy )
    • ペパボで技術責任者というのをやってます
    • Perl 界一の子だくさん?
      • 11 月に 4 人目が生まれる予定です
  •  
  •  
  • アジェンダ
    • イベント駆動型プログラミングによる非同期処理
    • Danga::Socket の非同期処理の仕組み
    • Perlbal の動作概要
    • Perlbal プラグインでの非同期処理
    • まとめ
  •  
  • イベント駆動型プログラミング
    • イベントを待機し、起こったイベントに従って処理を行うプログラミングパラダイム
    • フロー型プログラミングに対する概念
  • イベントの種類
    • I/O
      • I/O の読込可能 / 書込可能状態でイベント発生
    • タイマー
      • 一定時間後にイベント発生
    • シグナル
      • シグナル受信時にイベント発生
    • 子プロセス
      • 子プロセス終了時にイベント発生
  • メインループ
    • イベント駆動型プログラミングは、「イベント処理登録」 -> 「メインループ突入」という流れ
    • イベントループとも呼ばれる
    • イベント発生の有無をループする度に確認し、発生したイベントに応じた処理を行う
    • イベント処理後ループに戻り、次にイベント発生するまでループを繰り返す
    • このような流れで非同期に処理を行う
  • メインループの例 タイマー処理 I/O イベント待ち I/O イベント処理 ポストメインループ処理
  •  
  • Danga::Socket が対応してるイベント
    • I/O イベント
    • タイマーイベント
  • I/O イベント処理
    • Danga::Socket では以下の I/O 多重化機構に対応している
      • kqueue
      • epoll
      • poll
    • 適切な I/O 多重化機構を自動で選択してくれる
  • epoll の例
    • use Sys::Syscall
    • $epfd = epoll_create (1024);
    • epoll_ctl ( $epfd , EPOLL_CTL_ADD, $fd , EPOLLIN|EPOLLOUT);
    • while (1) { # ここからイベントループ
    • epoll_wait ( $epfd , 1024, $timeout, @events );
    • for $event ( @events ) {
    • # イベントに応じた処理
    • }
    • }
  • Danga::Socket での I/O イベント登録
    • use base ‘Danga::Socket’;
    • sub new {
    • # ファイルディスクリプタを new に渡す
    • $self->SUPER::new( $fd );
    • }
    • sub event_read {
    • # $fd が読込可能になった時に実行
    • }
    • sub event_write {
    • # $fd が書込可能になった時に実行
    • }
  • Danga::Socket での I/O イベント登録 その 2
    • Danga::Socket->AddOtherFds(
    • $fd => sub {
    • # read イベントでの処理
    • },
    • );
  • Danga::Socket での I/O イベント登録 その 3
    • Danga::Socket::Callback->new(
    • handle => $fd ,
    • on_read_ready => sub {
    • # read イベント処理
    • },
    • on_write_ready => sub {
    • # write イベント処理
    • },
    • );
  • Danga::Socket でのタイマーイベント登録
    • Danga::Socket->AddTimer(
    • 10,
    • sub {
    • # 10 秒後に実行される処理
    • },
    • }
  • Danga::Socket でのメインループの開始
    • Danga::Socket->EventLoop();
  • メインループ処理のおさらい タイマー処理 I/O イベント待ち I/O イベント処理 ポストイメインループ処理
  •  
  • Perlbal の動作(リバースプロキシとして利用の場合) BackendHTTP ClientProxy TCPListener Client Server ClientProxy Client BackendHTTP Danga::Socket ベースの オブジェクト
  • Perlbal プラグインの動作 (start_proxy_request フック) BackendHTTP ClientProxy TCPListener Client Server Plugin::Hoge 今回のターゲット
  •  
  • 対象となるフック
    • start_proxy_request フックでの実行を前提として解説していきます
  • 同期処理プラグインの場合 ClientProxy TCPListener Client Server Plugin::Sync Client
  • 非同期処理プラグインの場合 ClientProxy TCPListener Client Server Plugin::Async Client ClientProxy
  • プラグインを非同期にするには?
    • プラグインの処理を Danga::Socket のイベントループに組み込む
      • Danga::Socket ベースのクラスを作成
      • または Danga::Socket::Callback を利用して処理を書く
      • Danga::Socket::AddTimer でタイマー処理しても OK
      • 利用するライブラリにも注意
        • ブロックしないライブラリを使う
        • どうしてもブロックしてしまう処理は、 Gearman::Client::Async で外出し
  • プラグインを非同期にするには?
    • 非同期処理が完了したら、次のフェーズに処理を移す
      • プラグインのコールバックを利用
      • Perlbal 本体の修正も必要
  • 非同期処理するクラス
    • package My::Drizzle ;
    • use base ‘Danga::Socket’ ;
    • use Net::Drizzle ':constants' ;
    • sub new {
    • $self->SUPER::new($fh);
    • $self->watch_read(1);
    • }
    • sub event_read {
    • # DB リクエスト状態確認と完了時のコールバック処理
    • }
  • 注意
    • Danga::Socket::Callback をつかっても OK
    • AddOtherFds は使えない
      • AddOtherFds で登録されたファイルディスクリプタは、イベントループ突入の最初にしか EPOLL_CTL_ADD や EV_ADD されない
    • 直接 epoll_ctl とか呼び出してもいいけど、ポータビリティは低い
  • プラグイン register 処理
    • package Perlbal::Plugin::AsyncDb ;
    • sub register {
    • my ( $class, $svc ) = @_;
    • $svc->register_hook(
    • 'Async' => 'start_proxy_request',
    • &request_db ,
    • );
    • return 1;
    • }
  • 非同期処理クラスの呼び出し
    • sub request_db {
    • my Perlbal::ClientProxy $client = shift ;
    • My::Drizzle->new(
    • callback => sub {
    • # 完了時のコールバック処理
    • },
    • );
    • return 1; # 超重要ポイント!
    • }
  • return 0 の場合 BackendHTTP ClientProxy TCPListener Client Server Plugin::Async Plugin::Async の処理が 終わらないのに次の処理へ
  • return 1 &コールバック処理 BackendHTTP ClientProxy TCPListener Client Plugin::Async 処理を終了して イベントループへ Server return 1 コールバック
  • コールバックで必要な処理
    • ClientProxy の処理が handle_request() の途中で終了してイベントループに戻っている
    • プラグインの処理が完了したら、 ClientProxy の次の処理から再開
    • 停止してるのは、 handle_request() 中の以下のコード
    • return if $svc->run_hook(
    • 'start_proxy_request', $self
    • );
    • この次から処理を再開するようにする
  • コールバック処理
    • my Perlbal::ClientProxy
    • $client = shift ;
    • My::Drizzle->new(
    • callback => sub {
    • $client->{async_complete} = 1;
    • $client->handle_request;
    • },
    • );
  • ClientProxy::handle_request の修正
    • - return if $svc->run_hook(
    • - 'start_proxy_request', $self
    • - );
    • + unless ( $self->{async_complete} ) {
    • + return if $svc->run_hook(
    • + 'start_proxy_request', $self
    • + );
    • + }
    • + $self->{async_complete} = 0;
  •  
  • 非同期処理プラグインを書くポイント
    • 非同期にしたい処理は Danga::Socket のイベントループにつっこむ
    • プラグイン処理が呼び出されたら return 1
    • プラグイン処理が完了したら、コールバックで処理を再開してやる
    • Perlbal 本体の修正も必要
    • プラグインの実行順にも注意
      • return 1 するとそれ以降の同じフックのプラグインは実行されない
  •