Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

NanoStrand

961 Aufrufe

Veröffentlicht am

Veröffentlicht in: Software
  • Als Erste(r) kommentieren

NanoStrand

  1. 1. NanoStrand Smalltalkで分散ネットワーキング 第77回Smalltalk勉強会 合同会社ソフトウメヤ 梅澤真史
  2. 2. NanoStrandとは?? ● nanomsgのラッパー ● 気軽に高速なネットワークシステムが組めるよう にするためのライブラリ ● Smalltalk間はもちろん他言語とのやりとりもス ムーズに ● https://github.com/mumez/NanoStrand
  3. 3. 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. 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. 5. インストール(1) ● nanomsgのビルド ○ 32bitのCog VMを使う場合、32bit指定でコンパイル ○ Windowsの場合は32, 64bit用が両方できるので楽 ● ビルドした共有ライブラリ(libnanomsg)をVMのディレクトリに コピー CFLAGS=-m32 CXXFLAGS=-m32 LDFLAGS=-m32 ./configure
  6. 6. インストール(2) ● ConfigurationOfNanoStrandのロード ● 共有ライブラリを置いていないと定数初期化に失敗する ○ NnNbNanoMessageConstantsプールに値が入らない ○ 失敗した場合、ライブラリを置いて ”NnNbNanoMessageConstants initialize”すること Gofer new url: 'http://smalltalkhub.com/mc/MasashiUmezawa/NanoStrand/main'; package: 'ConfigurationOfNanoStrand'; load. (Smalltalk at: #ConfigurationOfNanoStrand) load
  7. 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. 8. 例: PULL/PUSHを書いてみる(2) "Start a Poller for multiplexing" poller := NnPoller startWithSockets: {sock1. sock2}. ● NnPollerでポーリング ● 異なるプロトコル、エンドポイントのSocketをまとめて登録できる ● 適切なタイミングで、onReceiveReady:, onSendReady:のコールバックが呼 び出される
  9. 9. 例: PULL/PUSHを書いてみる(3) 1 seconds wait. "The process ends after a second" poller stopAndCloseSockets. ● stopAndCloseSocketsでNnPollerを止める ● 実際にはensure:で確実に止めるようにしたほうが良い
  10. 10. 結果 ● Transcriptに表示させなければ20000qpsほど捌ける
  11. 11. 例: PUB/SUBで他言語との連携 (1) # PUSHのクライアント起動。"HelloWorld"を1秒ごとに送る $ nanocat --push --connect tcp://127.0.0.1:5585 -- data HelloWorld -i 1 ● クライアント側をnanocatに ○ Cで書かれたnanomsgの公式クライアント。テストに便利。
  12. 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
  13. 13. 例: PUB/SUBで他言語との連携 (3) ● サーバ側はPharo ○ PULLで受け取ったメッセージの数を10で割った余り(rem)を 計算 ○ 余りが0または5のときイベントとしてPUBLISHする
  14. 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. 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. 16. 例: PUB/SUBで他言語との連携 (6) poller := NnPoller new. poller startWithSockets: {sock1. sock2}. 30 seconds wait. poller stopAndCloseSockets. ● 30秒ほどポーリングして終了させる ○ 実際にはensure:を使ってstopさせること
  17. 17. 今後は? ● Smalltalk-Smalltalk間 ○ FFI部を充実させ、Squeak, CuisやVWに展開 ○ シリアライザとしてはMessagePackや StOMPを使える ● 他言語間 ○ Node.jsやVert.xなどとつなぐと広がりがありそう
  18. 18. NanoStrand-RPC ● RPCのI/Fを提供し便利に使えるようにする ○ ZeroMQに対するZeroRPC的な位置づけ ■ http://www.zerorpc.io ● 同期、非同期、oneway(送りっぱなし)をサポートする予定 ○ 現在は同期のみの実装 ○ http://smalltalkhub.com/#!/~MasashiUmezawa/NanoStrand-RPC
  19. 19. 例: 足し算サービスの利用 (1) ● 足し算するのみの簡単なサービスクラスを用意 NnRpcSampleService class >> plus: a with: b ^a+b ● #RpcSampleServiceという名前で登録しておく NnRpcServer addService: NnRpcSampleService named: #RpcSampleService
  20. 20. 例: 足し算サービスの利用 (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”
  21. 21. 速度は? ● 500回起動で80ms程度 [500 timesRepeat: [client invoke: #RpcSampleService selector: #plus: with: arguments: {1. 2}]] timeToRun. ”=> 0:00:00:00.078” ● なかなか速い ● Pure Smalltalkで書かれたRPCライブラリと比べてどうなのだろう か?
  22. 22. Remote Messagint Toolkit (RMT) ● 昔書いたPure SmalltalkのRPCライブラリ ○ http://smalltalkhub.com/#!/~MasashiUmezawa/RemoteMessagingToolkit ● 同期とonewayをサポート ● 某基幹系で毎日動いている ● Squeak用であったが、最近Pharo用に復活 ○ シリアライザはDataStreamからFuelに置き換えた
  23. 23. 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”
  24. 24. RPC系の予定 ● 非同期のサポート ○ Futureを返し、値の取得後にコールバックされる仕組み ● ORB? ○ 非同期ベースでいまさらORBっぽいものを作りたい ○ E言語に似た感じの何か
  25. 25. まとめ ● NanoStrandで、気軽に高速なネットワークプログラムが書け る ● いろいろなものとつないで楽しみましょう ● 今後の拡張にご期待ください!!

×