More Related Content Similar to NanoStrand (20) More from Masashi Umezawa More from Masashi Umezawa (15) NanoStrand3. nanomsgのこと
● 一言でいうと、Mini ZeroMQ (in C)
● マルチプラットフォーム
● 様々な通信パターン(Scalability Protocol)を提供
○ PUSH/PULL, REQ/REP, PUB/SUB, PAIR, SURVEY, BUS
● マルチトランスポート
○ TCPのみならずIPC、INPROCも
● 豊富な言語バインディング
○ http://nanomsg.org/documentation.html
4. NanoStrandの構成
● NanoStrand-FFI
○ FFIでnanomsg APIを呼ぶ部分
■ nanomsgのAPIをほぼそのまま使っている
■ NativeBoost版のみ (NanoStrand-NativeBoost-FFI)
● Legacy FFI版を作るとSqueakやCuisでも利用可能になる
● DLLCC版だとVisualWorks
● NanoStrand-Core
○ 上記FFI部を使いOO的なAPIを提供する
■ NnSocket(とそのサブクラス群)
5. インストール(1)
● nanomsgのビルド
○ 32bitのCog VMを使う場合、32bit指定でコンパイル
○ Windowsの場合は32, 64bit用が両方できるので楽
● ビルドした共有ライブラリ(libnanomsg)をVMのディレクトリに
コピー
CFLAGS=-m32 CXXFLAGS=-m32 LDFLAGS=-m32 ./configure
7. 例: PULL/PUSHを書いてみる(1)
"Setup PULL socket"
sock1 := NnPullSocket withBind: 'tcp://*:5575'.
sock1 onReceiveReady: [:sock | Transcript cr; show: '#PULL: ', sock receive asString].
"Setup PUSH socket"
sock2 := NnPushSocket withConnect: 'tcp://127.0.0.1:5575'.
sock2 onSendReady: [:sock | sock send: '#PUSH: ', Time now asString].
● パイプラインな処理
● NnPullSocketで受信、NnPushSocketで送信
8. 例: PULL/PUSHを書いてみる(2)
"Start a Poller for multiplexing"
poller := NnPoller startWithSockets: {sock1. sock2}.
● NnPollerでポーリング
● 異なるプロトコル、エンドポイントのSocketをまとめて登録できる
● 適切なタイミングで、onReceiveReady:, onSendReady:のコールバックが呼
び出される
9. 例: PULL/PUSHを書いてみる(3)
1 seconds wait. "The process ends after a second"
poller stopAndCloseSockets.
● stopAndCloseSocketsでNnPollerを止める
● 実際にはensure:で確実に止めるようにしたほうが良い
11. 例: PUB/SUBで他言語との連携 (1)
# PUSHのクライアント起動。"HelloWorld"を1秒ごとに送る
$ nanocat --push --connect tcp://127.0.0.1:5585 --
data HelloWorld -i 1
● クライアント側をnanocatに
○ Cで書かれたnanomsgの公式クライアント。テストに便利。
12. 例: PUB/SUBで他言語との連携 (2)
# SUBのクライアント起動。全てのイベントを受け付ける
$ nanocat --sub --connect tcp://127.0.0.1:5586 -A
● PUSHの他、SUB役のクライアントを2つ起動
# SUBのクライアント起動。"Evt:Rem0"イベントを受け付ける
$ nanocat --sub --connect tcp://127.0.0.1:5586 --subscribe Evt:Rem0 -A
14. 例: PUB/SUBで他言語との連携 (4)
received := OrderedCollection new. "A message box"
"Setup PULL socket"
sock1 := NnPullSocket withBind: 'tcp://127.0.0.1:5585'.
sock1 onReceiveReady: [:sock | | rec |
rec := (sock receiveFor: 200 timeoutDo: ['']) asString.
rec ifNotEmpty: [
received add: rec. "Stock the received message"
Transcript cr; show: 'Received:', rec, ':', Time now printString].
].
15. 例: PUB/SUBで他言語との連携 (5)
"Setup PUB socket"
sock2 := NnPubSocket withBind: 'tcp://127.0.0.1:5586'.
sock2 onSendReady: [:sock | |rem |
rem := received size rem: 10. "10で割った余りを出す"
"余りが0か5の時、イベントとして送る"
rem = 0 ifTrue: [sock send: 'Evt:Rem0:', Time now printString].
rem = 5 ifTrue: [sock send: 'Evt:Rem5:', Time now printString].
].
16. 例: PUB/SUBで他言語との連携 (6)
poller := NnPoller new.
poller startWithSockets: {sock1. sock2}.
30 seconds wait.
poller stopAndCloseSockets.
● 30秒ほどポーリングして終了させる
○ 実際にはensure:を使ってstopさせること
20. 例: 足し算サービスの利用 (1)
● 足し算するのみの簡単なサービスクラスを用意
NnRpcSampleService class >> plus: a with: b
^a+b
● #RpcSampleServiceという名前で登録しておく
NnRpcServer addService: NnRpcSampleService
named: #RpcSampleService
21. 例: 足し算サービスの利用 (2)
● サーバの起動
server := NnRpcServer bind: 'tcp://127.0.0.1:6677'.
server start.
● クライアントの接続、RPC呼び出し
client := NnRpcClient connect: 'tcp://127.0.0.1:6677'.
client invoke: #RpcSampleService
selector: #plus:with: arguments: {1. 2}. ”=> 3”
22. 速度は?
● 500回起動で80ms程度
[500 timesRepeat: [client invoke: #RpcSampleService selector: #plus:
with: arguments: {1. 2}]] timeToRun. ”=> 0:00:00:00.078”
● なかなか速い
● Pure Smalltalkで書かれたRPCライブラリと比べてどうなのだろう
か?
23. Remote Messagint Toolkit (RMT)
● 昔書いたPure SmalltalkのRPCライブラリ
○ http://smalltalkhub.com/#!/~MasashiUmezawa/RemoteMessagingToolkit
● 同期とonewayをサポート
● 某基幹系で毎日動いている
● Squeak用であったが、最近Pharo用に復活
○ シリアライザはDataStreamからFuelに置き換えた
24. RMTで計測
● 500回起動で1300ms程度
service := (RmtTcpService on: 4566) acceptorClass: RmtRpcAcceptor.
service start.
RmtRpcAcceptor receiverDictionary at: #RpcSampleService
put: NnRpcSampleService.
client := RmtRpcConnector connect: 'localhost' port: 4566.
[500 timesRepeat: [client invoke: #RpcSampleService selector: #plus:with:
arguments: {1. 2}]] timeToRun. ”=> 0:00:00:01.33”