Upload
masashi-umezawa
View
311
Download
1
Embed Size (px)
Citation preview
VerStixPharo Smalltalk と Vert.x
第102回Smalltalk勉強会
合同会社ソフトウメヤ 梅澤真史
VerStixとは
● Vert.xと連携するためのクライアントライブラリ
○ https://github.com/mumez/VerStix● 簡潔かつリアクティブな形で
Pharoと外部サービスとの連携を行える
Vert.x● リアクティブなシステム開発のためのツールキット
○ http://vertx.io/● 非同期APIでWeb, DB, MQ, 認証などのサービスと連携
○ Verticle (いわゆるActorのようなもの)○ EventBus経由で通信
● マルチ言語をサポート(Java, JavaScript, Groovy, Ruby, Ceylon, Kotlin, Scala)
Vert.x EventBus● Vert.xの根幹となる非同期通信機構
○ http://vertx.io/docs/vertx-core/java/#event_bus● イベントをpeer-to-peer、pub-subなど様々な形式で送信可能
● イベントの配送順序は保証するが厳密な配送保証はしない
● TCP EventBus Bridgeにより、JVM言語以外との連携も可能
○ https://github.com/vert-x3/vertx-tcp-eventbus-bridge
TCP EventBus Bridge Clients● Swift, C++, C#, Python, Goなど
○ https://github.com/vert-x3/vertx-awesome#vertx-event-bus-clients● Smalltalk版がVerStixという位置づけ
○ 自動再接続や簡易なコネクションプールも提供
○ VerStix-Core パッケージのみ
■ わずか6クラスでできている
● Stick上に作られているため
TCP EventBus Bridge のプロトコル
● HTTPよりも簡単
○ TCPのSocketでJSONを送るだけ
○ 4バイトのメッセージ長+JSON● JSONの形式
○ address○ headers○ body○ メッセージ種別 (send, publish, register, unregister)○ (replyAddress)
Vert.xのインストール
● SDKMAN が楽
○ 様々なプラットフォームに対応
○ JDM系のSDKのインストールをまとめて行える
● インストール後は vertx コマンドが使えるようになる
$ sdk install vertx
VerStixのインストール
● Catalog Browserから
○ 'verstix'で検索し、'install stable version'● あるいはMetacelloでロード
Metacello new
smalltalkhubUser: 'Pharo' project: 'MetaRepoForPharo60';
configuration: 'VerStix';
version: #stable;
get; load.
サンプルのVerticleを起動
● 動作確認用のサンプルVerticle(groovy)を入手
○ https://github.com/mumez/VerStix/blob/master/example/TcpEventBusBridgeEchoServer.groovy■ helloイベントの受信、echoイベントの送受信ができる
● vertxコマンドでVerticleを起動
○ --instances <n> で複数起動もできる(ラウンドロビン)○ --ha でクラスタリングもできる(プロセス間でRR)
$ vertx run TcpEventBusBridgeEchoServer.groovy
VerStixからのイベント送信
● 接続
eventBus := VsEventBus host: 'localhost' port: 7000.eventBus connect.
● 'echo'イベントの送信
eventBus send: {'value'->'HELLO from Smalltalk'} to: 'echo'.
$ got: {"value":"HELLO from Smalltalk"} => コンソールに表示される
コールバックの指定
● 送信時にcallbackの指定が可能
○ サーバでの処理が終わると非同期で呼び出される
● 'echo'なので送信したメッセージのbodyそのものが
返ってきてインスペクタが開く
eventBus send: {'value'-> Time now asString} to: 'echo' callback: [:msg | msg body inspect].
Pub/Subをしてみる
● VsEventBus>>subscribe:callback:でイベントハンドラを登録
● VsEventBus>>publish:to:でイベントをブロードキャスト
● 複数のPharoイメージで試してみましょう
eventBus subscribe: 'echo' callback: [:msg | msg body inspect].
eventBus publish: {'value'-> Time now asString} to: 'echo'.
Goとつないでみる
● vxc (Goで書かれたVert.x EventBusのCLI)を使用
○ https://github.com/cinterloper/vxc● echoイベントをsubscribeさせてみる
● Pharoからpublishすると
$ go run app.go -l -n echo
$ {"value":"1:39:31.546674 pm"}
Vert.x側のイベントハンドラ
● イベントに対するConsumerを指定
vertx.eventBus().consumer("echo", {msg ->
//msg.reply(new JsonObject().put("value", "Hello);
msg.reply(msg.body());
});
● JsonObjectにしてreply()で値を返す
EventBusBridgeの起動
● 生成時にBridgeOptionsで送受信するイベントを設定
TcpEventBusBridge bridge = TcpEventBusBridge.create(vertx,
new BridgeOptions()
.addInboundPermitted(new PermittedOptions().setAddress("hello"))
.addInboundPermitted(new PermittedOptions().setAddress("echo"))
.addOutboundPermitted(new PermittedOptions().setAddress("echo")));
bridge.listen(7000, {res -> System.out.println("Ready: "+ bridge)});
● listen()で起動
応用例: bolt.x● Neo4jの純正Bolt Protocol DriverをVerStixから呼び出す
○ サーバ (Java)■ https://github.com/mumez/bolt.x
○ クライアント (Pharo)■ http://smalltalkhub.com/#!/~MasashiUmezawa/Boltx
● PharoからJavaのBolt DriverによるNeo4jへのアクセスが可能
● 非同期APIが使えるようになる
○ REST APIでは提供されていない
bolt.xのインストール (サーバ側)
$ $ ./bin/neo4j console
● Neo4jを入手○ https://neo4j.com/download/community-edition/
■ tarballを展開して起動
○ http://localhost:7474/browser/ にアクセスし、サンプルのMovie Graphを作成しておく
● Githubからbolt.xをcloneしてredeploy.shを起動
$ $ bash redeploy.sh
bolt.xのインストール (クライアント側)
Gofer newurl: 'http://smalltalkhub.com/mc/MasashiUmezawa/Boltx/main'; package: 'ConfigurationOfBoltx';load.
(Smalltalk at: #ConfigurationOfBoltx) load
● Goferでいつものやつ
非同期APIでのCypher実行
client := BxCypherClient host: 'localhost' port: 7000. req := client asyncQueryByCypher: 'MATCH (n:Movie{released:$y}) RETURN n' params: {'y'->2000}.
● asyncQueryByCypher:paramsを使う
● ifNext:で結果をpushでrowごとに取得
req ifNext: [:val | Transcript cr; show: val ].
● ifDone:で結果をまとめて取得
req ifDone: [ :vals | vals inspect ].
非同期で書き込み
client := BxCypherClient host: 'localhost' port: 7000. req := client writeByCypher: 'MERGE (a:Person {name: $name1})MERGE (b:Person {name: $name2})MERGE (a)-[r:KNOWS]->(b)' params: {'name1'->'test1'. 'name2'->'test2'}.
● writeByCypher:params:を使う
● ifFailed:でエラーがあった時に通知
req ifFailed: [ :error | error inspect ]
非同期でバルク書き込み
client := BxCypherClient host: 'localhost' port: 7000. req := client writeBySameCypher: 'MERGE (a:Person {name: $name1})MERGE (b:Person {name: $name2})MERGE (a)-[r:KNOWS]->(b)' paramsArray: ((1 to: 1000)
collect: [:idx | {'name1'->idx asString. 'name2'->(idx+1) asString}]).
● 同一のCypherでパラメータだけを変更して大量書き込み
同期APIとの比較
graphDb := N4GraphDb new. req := client queryByCyphers:( (1 to: 1000) collect: [ :idx | {'MERGE (a:Person {name: $name1})MERGE (b:Person {name: $name2})MERGE (a)-[r:KNOWS]->(b)'. {'name1'->'test1'. 'name2'->'test2'}}]).
● Neo4reStの場合
○ 処理が終わるまでPharo側はブロック○ 同一の重複したCypherを送っていて無駄が多い
Vert.x側での留意点
vertx.<JsonObject>executeBlocking(future -> { basicExecute(msg, future);}, true, res -> { msg.reply(res.result());});
● 各処理がブロッキングで止まらないようにする○ 外部DB等の同期APIを呼び出す時に注意
その他の応用例
● EventBus経由でVert.x JDBC Clientを使えるようにする○ PharoからMySQLやOracleに接続できるようになる
● EventBus経由で認証系APIとつなぐ○ PharoからJWTやShiroなどの利用が可能になる
まとめ
● VerStixを使うと簡単なイベント送信のAPIで、既存のサービ
スを連携させることができる
● 同期のみのAPIを非同期化したり、何かと手厚いJavaのSDK
やドライバをPharoから手軽に利用したりするには有効