26
NanoStrand Smalltalkで分散ネットワーキング 77Smalltalk勉強会 合同会社ソフトウメヤ 梅澤真史

NanoStrand

Embed Size (px)

Citation preview

Page 1: NanoStrand

NanoStrandSmalltalkで分散ネットワーキング

第77回Smalltalk勉強会

合同会社ソフトウメヤ 梅澤真史

Page 2: NanoStrand

NanoStrandとは??● nanomsgのラッパー

● 気軽に高速なネットワークシステムが組めるよう

にするためのライブラリ

● Smalltalk間はもちろん他言語とのやりとりもス

ムーズに

● https://github.com/mumez/NanoStrand

Page 3: NanoStrand

nanomsgのこと

● 一言でいうと、Mini ZeroMQ (in C)● マルチプラットフォーム

● 様々な通信パターン(Scalability Protocol)を提供

○ PUSH/PULL, REQ/REP, PUB/SUB, PAIR, SURVEY, BUS ● マルチトランスポート

○ TCPのみならずIPC、INPROCも

● 豊富な言語バインディング

○ http://nanomsg.org/documentation.html

Page 4: NanoStrand

NanoStrandの構成

● NanoStrand-FFI○ FFIでnanomsg APIを呼ぶ部分

■ nanomsgのAPIをほぼそのまま使っている

■ NativeBoost版のみ (NanoStrand-NativeBoost-FFI)● Legacy FFI版を作るとSqueakやCuisでも利用可能になる

● DLLCC版だとVisualWorks

● NanoStrand-Core○ 上記FFI部を使いOO的なAPIを提供する

■ NnSocket(とそのサブクラス群)

Page 5: NanoStrand

インストール(1)● nanomsgのビルド

○ 32bitのCog VMを使う場合、32bit指定でコンパイル

○ Windowsの場合は32, 64bit用が両方できるので楽

● ビルドした共有ライブラリ(libnanomsg)をVMのディレクトリに

コピー

CFLAGS=-m32 CXXFLAGS=-m32 LDFLAGS=-m32 ./configure

Page 6: NanoStrand

インストール(2)● ConfigurationOfNanoStrandのロード

● 共有ライブラリを置いていないと定数初期化に失敗する

○ NnNbNanoMessageConstantsプールに値が入らない ○ 失敗した場合、ライブラリを置いて

”NnNbNanoMessageConstants initialize”すること

Gofer new url: 'http://smalltalkhub.com/mc/MasashiUmezawa/NanoStrand/main'; package: 'ConfigurationOfNanoStrand'; load.(Smalltalk at: #ConfigurationOfNanoStrand) load

Page 7: NanoStrand

例: 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で送信

Page 8: NanoStrand

例: PULL/PUSHを書いてみる(2)

"Start a Poller for multiplexing"

poller := NnPoller startWithSockets: {sock1. sock2}.

● NnPollerでポーリング● 異なるプロトコル、エンドポイントのSocketをまとめて登録できる● 適切なタイミングで、onReceiveReady:, onSendReady:のコールバックが呼

び出される

Page 9: NanoStrand

例: PULL/PUSHを書いてみる(3)

1 seconds wait. "The process ends after a second"

poller stopAndCloseSockets.

● stopAndCloseSocketsでNnPollerを止める

● 実際にはensure:で確実に止めるようにしたほうが良い

Page 10: NanoStrand

結果

● Transcriptに表示させなければ20000qpsほど捌ける

Page 11: NanoStrand

例: PUB/SUBで他言語との連携 (1)

# PUSHのクライアント起動。"HelloWorld"を1秒ごとに送る

$ nanocat --push --connect tcp://127.0.0.1:5585 --

data HelloWorld -i 1

● クライアント側をnanocatに○ Cで書かれたnanomsgの公式クライアント。テストに便利。

Page 12: NanoStrand

例: 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

Page 13: NanoStrand

例: PUB/SUBで他言語との連携 (3)● サーバ側はPharo

○ PULLで受け取ったメッセージの数を10で割った余り(rem)を

計算

○ 余りが0または5のときイベントとしてPUBLISHする

Page 14: NanoStrand

例: 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].].

Page 15: NanoStrand

例: 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].].

Page 16: NanoStrand

例: PUB/SUBで他言語との連携 (6)

poller := NnPoller new.poller startWithSockets: {sock1. sock2}.30 seconds wait.poller stopAndCloseSockets.

● 30秒ほどポーリングして終了させる

○ 実際にはensure:を使ってstopさせること

Page 17: NanoStrand
Page 18: NanoStrand

今後は?● Smalltalk-Smalltalk間

○ FFI部を充実させ、Squeak, CuisやVWに展開

○ シリアライザとしてはMessagePackや StOMPを使える

● 他言語間

○ Node.jsやVert.xなどとつなぐと広がりがありそう

Page 19: NanoStrand

NanoStrand-RPC● RPCのI/Fを提供し便利に使えるようにする

○ ZeroMQに対するZeroRPC的な位置づけ

■ http://www.zerorpc.io

● 同期、非同期、oneway(送りっぱなし)をサポートする予定

○ 現在は同期のみの実装

○ http://smalltalkhub.com/#!/~MasashiUmezawa/NanoStrand-RPC

Page 20: NanoStrand

例: 足し算サービスの利用 (1)● 足し算するのみの簡単なサービスクラスを用意

NnRpcSampleService class >> plus: a with: b^a+b

● #RpcSampleServiceという名前で登録しておく

NnRpcServer addService: NnRpcSampleService named: #RpcSampleService

Page 21: NanoStrand

例: 足し算サービスの利用 (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”

Page 22: NanoStrand

速度は?● 500回起動で80ms程度

[500 timesRepeat: [client invoke: #RpcSampleService selector: #plus:with: arguments: {1. 2}]] timeToRun. ”=> 0:00:00:00.078”

● なかなか速い

● Pure Smalltalkで書かれたRPCライブラリと比べてどうなのだろう

か?

Page 23: NanoStrand

Remote Messagint Toolkit (RMT)● 昔書いたPure SmalltalkのRPCライブラリ

○ http://smalltalkhub.com/#!/~MasashiUmezawa/RemoteMessagingToolkit

● 同期とonewayをサポート

● 某基幹系で毎日動いている

● Squeak用であったが、最近Pharo用に復活

○ シリアライザはDataStreamからFuelに置き換えた

Page 24: NanoStrand

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”

Page 25: NanoStrand

RPC系の予定

● 非同期のサポート

○ Futureを返し、値の取得後にコールバックされる仕組み

● ORB?

○ 非同期ベースでいまさらORBっぽいものを作りたい

○ E言語に似た感じの何か

Page 26: NanoStrand

まとめ

● NanoStrandで、気軽に高速なネットワークプログラムが書け

● いろいろなものとつないで楽しみましょう

● 今後の拡張にご期待ください!!