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

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

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

3,236

Published on

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
3,236
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
7
Comments
0
Likes
2
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

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

×