いわゆる分散処理の例を作ってあってsinatra-rocketio-lindaのsampleの中に入れてあったんだけど、blogに書くのを忘れていたので書きます。
センサーのデータを流して受け取る、いわゆる「pub-sub」的な使い方の他にも、Hadoopがやっているようなタスク分散が簡単に書けるよという例です。
実行環境 http://hello-linda.shokai.org
ソースコード https://github.com/shokai/linda-hello-world
というのも昨日wise9さんに取り上げていただいて、そういえば全然サンプルコードとか整備・整理してない事を思い出したので書こうと思った。
PC遠隔操作編の拡張版みたいなやつです。
動かし方(ごく普通に実行)
clientとworkerをそれぞれ開き、「request!」ボタンを押します。worker側のウィンドウで式がevalで実行されます。
evalなのでclientに「alert(“hoge”)」とか書いてrequestすると、worker側でalertのダイアログがポップアップします。
動かし方(分散実行)
hadoop(map/reduce)がやっているような、仕事を複数のワーカーに分散実行させて結果を一箇所にまとめる処理をブラウザ上のJavaScriptだけで書けます。まずclientを1つ開きます。
次にworkerを3つ開きます。
clientの「request!」ボタンを押すと、3つのworkerが順番に仕事してくれます。
webブラウザで実行されているので、workerのwebページを手持ちのスマホやタブレットで開けば分散実行に参加できます。
動かし方(仕事を貯めておいて実行)
仕事を貯めておいて、ワーカーが現れるまで待ちます。現れたら一気に実行されます。まずclientを1つ開き、「requst!」ボタンを連打します。
次にworkerを1つ開くと、今まで溜まっていたrequestが一気に実行されます。
動作原理
3つとも同じコードです。Lindaのtake(削除しつつ読み出し)をうまく使うと、こういう処理が簡単に書けますLindaはだれでも読み書きできるタプルスペース(共有メモリ領域)を使った並列処理の実行環境です。
命令はwrite/read/take/watchという4種類しかありません。
writeは書き込み、readはマッチするタプル最新の1個を読み出し、takeはreadしながら削除です。
watchはマッチするタプルがwriteされた瞬間に通知されます。watchはセンサーデータをストリーミングする時などに便利です。
Lindaのタプル読み出しは少し特殊です。
takeとreadは要求しているタプル(データのこと。ArrayかHash)があれば即座に値を読み出しますが、見つからない場合、値が現れるまで待ちます。これが分散実行に使えます。
read/take/watchのマッチングは、「Arrayの前方一致」です。
つまり[“sensor”]は[“sensor”,”light”,20]にマッチするし、[“sensor”,”temperature”, 25]にもマッチします。
[“sensor”,”light”]に範囲を狭めると、[“sensor”,”light”,20]や[“sensor”,”light”, 123]にはマッチしますが、[“sensor”,”temperature”,25]等にはマッチしません。
「Arrayの前方一致」なので、1つ目の要素が”sensor”で2つ目の要素が”light”なタプルにしかマッチしないのです。
タプルの構造によってどんなデータが欲しいかを指定します。
タプルスペースはなんでも入れられるハブです。そこにクライアントをぶら下げるとread/take/watchを駆使してイベント駆動でデータを受け取ると便利だよという事ですね。
ちなみに「だれでも読み書きできる共有メモリ空間」なのですが、Lindaの実装はRubyのwebアプリケーションフレームワーク「Sinatra」のプラグインになっています。
Sinatraでログイン画面とか作れば、特定の人しか書き込みできないようにするとか、ユーザー毎にタプルスペースを分けるとかも可能です。
あとで書く
Lindaでの色々なパターンでのデータの流し方とその例をまとめる- pipeline
- pub-sub
- req-res
- job-queue
- broadcast
- multisub