RubyでEvent-DrivenなWebプログラミングを楽しむ環境が整ってきた件@KazkiMatz
Background’08 3月’07 4月国土交通省’02 4月’83 9月’07 3月’09 12月IPA未踏案件京都大学工学部電気電子工学科head’06 8月’09 11月’08 4月
(復習)Event-Drivenなアーキテクチャが重要である理由20ms100ms80ms前処理DBレスポンス待ちViewレンダリングViewレンダリング前処理DBレスポンス待ちViewレンダリングViewレンダリングDBレスポンス待ちDBレスポンス待ち前処理Viewレンダリング前処理CPUリソースを有効活用するには?-> 1CPUにつき、2インスタンス以上立ち上げる
思考実験10ms10sec (10,000ms)40ms前処理バックエンドレスポンス待ち後処理前処理バックエンドレスポンス待ち後処理…1CPUにつき、約200インスタンス必要!?
思考実験Railsの場合:1インスタンスにつき、フットプリントが100MB×200個= 20GB現実的ではないC10K問題
解決策Event-Drivenに処理する(Reactorモデル)軽量スレッドを活用(Fiber, Neverblock)コンテキストの保持面から考えると…1 ⇒ closureベース(JSにそっくり!)2 ⇒ 軽量スレッドの継承ベース
現時点での顔ぶれ(Ruby界隈)EventMachineAsync-WebサーバThinEbbAsync-WebフレームワークCrampasync_sinatra周辺環境Gearman
Gearman?分散処理フレームワークEvent-Driven サーバプログラミングと抜群に相性がいい(重い処理をバックエンドに投げ、レスポンスが帰ってくるまで待つ)ブロックしないクライアントが無かったので、EventMachine::Protocols::GearmanをGithub上で作成中。http://github.com/KazkiMatz/em-gearman-client
Cramp?登場して間もないWebフレームワーク手軽にEvent-DrivenなWebアプリケーションを書けるEventMachineを使っているRackをサポートThin / Rainbows! 上で動作http://m.onkey.org/2010/1/7/introducing-cramp
CrampJSONを返すAPIエンドポイントの実装例classTestController < Cramp::Controller::Actionon_start :maindef main~~~self.respond({ … })enddefrespond hash    render hash.to_json    finishendend
Crampdefmain    res = {}    joint = AsyncJobsJoint.newjoint.callback = Proc.new{ self.respond(res) }    ticket4memcache = joint.take_ticket@@cache ||= EM::P::Memcache.connect'localhost', 11211@@cache.get(someKey.to_sym){|item|      res[:memcache_response] = item if itemjoint.return_ticket ticket4memcache    }    ticket4gearman = joint.take_ticketgearman = EM::P::Gearman.connect‘localhost', 7003    task = gearman.create_task(‘someJob’, someInput)task.on_complete{|item|gearman.close_connection_after_writing      res[:gearman_response] = itemjoint.return_ticket ticket4gearman    }task.on_fail {gearman.close_connection_after_writingjoint.return_ticket ticket4gearman    }task.queue!    ticket4db = joint.take_ticketUser.where(User[:id].eq(params[:user_id])).first {|user|      res[:db_response] = userjoint.return_ticket ticket4db    }end全体終了後のコールバックを登録Memcached, Gearman, MySQLの3者に、“同時並行的に”データを取りに行き、AsyncJobsJoint(後述)で待ち合わせている。
Cramp内、待ち合わせのお供に…classAsyncJobsJointdefcallback= proc@callback = procenddeftake_ticket@tickets ||= []    ticket = (@tickets.max || 0) + 1@tickets << ticket    ticketenddefreturn_ticket ticket@tickets.delete(ticket)@callback.callif@tickets.empty?endend
Summary2007年にEventMachineが登場してはや3年、環境はかなり整ってきた使いこなせるかどうかで、必要なサーバリソースが一桁以上変わることがあるCrampよさげ一つのアプリケーション内で、同期Webフレームワーク(ex. Rails)と非同期Webフレームワーク(ex. Cramp)を使い分ける一歩踏み出すのに、今ほどいい時期はない
ご清聴ありがとうございました松本 一輝  (KazkiMatz)email:	kazki.matz@gmail.comblog:	http://d.hatena.ne.jp/kazuk_i/twitter: @KazkiMatz

Async Programming on Ruby