イベント駆動プログラミングとI/O多重化

Preview:

DESCRIPTION

2年ぐらい前の社内勉強会で使った資料。

Citation preview

イベント駆動プログラミングと

I/O多重化

イベント駆動プログラミング

イベントを待機し、起こったイベントに従って処理を行うプログラミングパラダ

イム

フロー駆動型プログラミングと呼ばれる従来のプログラミングパラダイムに対す

る概念

GUIプログラミング

キーやマウスの入力をイベントとして受け取って処理

ネットワークプログラミング

ネットワーク I/Oを多重化して1プロセス 1スレッドで複数のネットワーク接続を同時に捌

非イベント駆動なネットワークプログラミング

processor

thread

processor

thread

processor

thread

Client

Client

Client

イベント駆動なネットワークプログラミング

processor

thread

Client

Client

Client

今回はこっちがメイン

The C10K Problem

イベント駆動型プログラミングの処理フ

ロー

element.addEventListener( ’click’, function(){ console.log(‘hoge’) }, true);

これってどう動いてるの?

イベントループ(メインループ)

イベント待ち

イベント処理

後処理

イベント登録

高レベルな言語ではイベントループを自分で書く必要はない

element.addEventListener( ’click’, function(){ console.log(‘hoge’) }, true);

後で自分で書くとどうなるか解説します

イベントの種類

タイマー

I/O

シグナル

子プロセス

イベント待ち

イベント処理

後処理

イベント登録

イベントループの話おしまい

I/O多重化

ネットワークプログラミングにおけるイベント駆

動の要

これなくして 1プロセス 1スレッドで複数のネットワーク接続を同時捌くこと

はできない

なぜ 1プロセス 1スレッドで捌く必要があるの

か?

The C10K Problemでググれ

I/O多重化の仕組み

I/Oイベント待ち

I/Oイベント処理

後処理

I/Oイベント登録

非同期 echoサーバを題材にサンプルコードで見

多重化してない例

int sock = socket(PF_INET, SOCK_STREAM);bind(sock, addr);listen(sock);

while ( 1 ) { int new_sock = accept(sock, &addr); char buf[100]; size_t size = read(new_sock, buf, 100); if ( size == 0 ) { close(new_sock); } else { write(new_sock, buf, size); }}

多重化での処理の流れ

サーバ

クライアント

待ち受けソケット(イベント監視対象につっこむ)

サーバ

クライアント

待ち受けソケット(イベント監視対象)

サーバ

クライアント

待ち受けソケット(イベント監視対象)

接続ソケット(イベント監視対象につっこむ)

accept(sock)

サーバ

クライアント

待ち受けソケット(イベント監視対象)

接続ソケット(イベント監視対

象)

selectによる多重化

https://gist.github.com/mizzy/5343931

epollによる多重化

https://gist.github.com/mizzy/5343937

多重化用関数

selectpoll

epollkqueue

/dev/poll

select/pollは全部のソケットを調べる

epoll, kqueue, /dev/pollはイベントが発生したソケットだけを調べることができる

イベントライブラリ

libeventlibev

OSによる違いを吸収してくれる

I/O多重化以外にもタイマーイベントやシグナルイベントなんかも扱える

node.jsはlibevent + libeio

各種言語による非同期 echoサーバ

Perl(AnyEvent)

https://gist.github.com/mizzy/5343944

Ruby(EventMachine)

https://gist.github.com/mizzy/5343953

Python(twisted)

https://gist.github.com/mizzy/5343956

Python(eventlet)

https://gist.github.com/mizzy/5343959

node.js

https://gist.github.com/mizzy/5343964

イベント駆動プログラミングのデメリット

マルチコアでスケールしない

処理の流れが追いにくい書きにくい

var req_to_zenrin = http.request( options, function(res2) { res2.on('end', function() { res.end(); }); res2.on('data', function(chunk) { res.write(chunk); }); });

var referer;sdb.getItem( 'gha', host, function( error, result ) { if ( result ) { referer = ‘http://hoge.com/’; } });

// sdb.getItem()終了前に次の処理

sdb.getItem( 'gha', host, function( error, result ) { if ( result ) { access_to_zenrin('http://hoge.com'); } else { access_to_zenrin(); } });

ネットワークアクセスを伴う

処理をすべて非同期で書かないといけない

なので libmysqlclientは使えない

node-mysqlは libmysqlclient相当の処理を再実装してる

(っぽい)

参考文献

Recommended