coursera で受けている, POSA の講義で出てきた Reactor Pattern について調べてみたまとめです.
Reactor Pattern とは
イベント駆動のためのデザインパターン.
The reactor design pattern is an event handling pattern
for handling service requests delivered concurrently
to a service handler by one or more inputs.
特徴
- イベント (入力データ) を, 処理や状態を表すハンドラ (メソッド or サブクラス) にディスパッチ (結びつける) する.
- ハンドラごとに責務を分割できるので OOP 向き.
- ハンドラ以外の部分はフレームワークに隠蔽されていることがおおい.
EventMachine は Reactor パターンの高性能な実装さ.
Android は状態ごとにハンドラが呼び出される.
- onCreate ()
- onResume ()
- onDestory ()
Spring Framework では, GET や POST の HTTP request は, それぞれ対応するメソッドにコールバックされる.
Structure
- Resources: 入力データ
- Synchronous Event Demultiplexer:入力データを拾うためのイベントループ. シングルスレッドで loop していることが特徴 (Synchronous).
- Dispatcher: ハンドラを管理する. Demultiplexer から通知を受けたら, Resource を Handler に Dispatch する (select など)
- Handler: Resource に関連付けられた処理.
Socket Programming における Reactor Pattern
Socket Programming ででてくる Reactor は, 狭義の Reactor Pattern のようだ.
特徴
- すべての処理をシングルスレッドで実施する.
- マルチスレッドを利用しなくても, 非同期処理がかける.
- スレッドやプロセス数の制限なしに, クライアントからの要求に答えることができる.
実装方法
- ソケットを select で監視する. 読み取り可能, 書き込み可能なソケットのみに対して処理を実施する.
- 遅い回線があるときに, その回線に引きずられて Reactor が他の処理をできない. すべての処理が Blocking される.そんなときは, non-blocking write を利用する.
sample
以下のリンクのサンプルをそのまま写経しました.
write_socks = hosts.map do |host|
TCPSocket.new (host, 80)
end
read_socks = []
# handler
write_proc = lambda{|sock|
sock.write (request)
}
# handler
read_proc = lambda{|sock|
sock.read
sock.close
}
# Reactor
until (write_socks + read_socks).empty?
# Demultiplexer
r_socks, w_socks, e_socks = IO.select (read_socks, write_socks)
# Dispatcher
if ws = w_socks.first
write_proc.call (ws)
read_socks << ws
write_socks.delete (ws)
end
# Dispatcher
if rs = r_socks.first
read_proc.call (rs)
read_socks.delete (rs)
end
end
Working With TCP Socket における Reactor Pattern.