2019年6月6日木曜日

Ruby で JSON-RPC 入門

概要

RPC は Remote Procedure Call の略でネットワー上の別のホストに実装されている関数を呼び出すための仕様です
JSON-RPC はリクエストとレスポンスを JSON でやり取りする RPC で、リクエストの JSON に含まれた関数をコールすることができます
今回は over HTTP という一番簡単なインタフェースを使って実現してみました
なお今回はとりあえず試してみたかったので jimson というライブラリを使っています
あまり更新がないのでプロダクトなどでの仕様はおすすめしませんがサクッと実装することができます

環境

  • macOS 10.14.5
  • Ruby 2.6.2p47
    • jimson 0.11.0

ライブラリインストール

  • bundle init
  • vim Gemfile
gem "jimson"
  • bundle install --path vendor

JSON-RPC サーバ

  • vim app.rb
require 'jimson'

class MyRPCHandler
  extend Jimson::Handler

  def sum(a, b)
    return a + b
  end
end

server = Jimson::Server.new(MyRPCHandler.new)
server.start
  • bundle exec ruby app.rb

サーバ側はこれだけです
クライアントを作成してこの sum メソッドをコールしてみましょう

curl クライアント

curl を使います
JSON-RPC 2.0 ではリクエストやレスポンスの仕様 が決まっているのでそれ通りにリクエストが通るか確認します

  • curl -XPOST -d '{"jsonrpc":"2.0","method":"sum","params":[1,2],"id":"1"}' localhost:8999

=> {"jsonrpc":"2.0","result":3,"id":"1"}

こんな感じでコールすることができます
リクエストには jsonrpc, method, params, id の 4 つの要素があります
レスポンスは jsonrpc, result, id の 3 つになります
id はリクエストしたものがそのままレスポンスにも返ってきます

バッチ

RPC の特徴としてバッチ呼び出しという機能があります
定義されている関数を 1 回のリクエストで複数回コールすることができます

curl -XPOST \
localhost:8999 \
-d @- << EOF
[
  {
    "jsonrpc":"2.0",
    "method":"sum",
    "params":[1,2],
    "id":"1"
  },
  {
    "jsonrpc":"2.0",
    "method":"sum",
    "params":[3,4],
    "id":"2"
  }
]
EOF

=> [{"jsonrpc":"2.0","result":3,"id":"1"},{"jsonrpc":"2.0","result":7,"id":"2"}]

こんな感じでリクエストの JSON を配列で定義するだけです
結果も配列で戻ってきます
id 要素はバッチ処理でどのリクエストがどのレスポンスかを紐付けるために使われたりします

Ruby のクライアント

  • vim client.rb
require 'jimson'

client = Jimson::Client.new("http://localhost:8999")
p client.sum(1, 2)
sum1 = sum2 = nil
Jimson::Client.batch(client) do |batch|
  sum1 = batch.sum(1, 2)
  sum2 = batch.sum(3, 4)
end
p sum1.result
p sum2.result

バッチの場合は Jimson::Client.batch を使います
呼び出す関数をブロックで定義します

最後に

Ruby で JSON-RPC に入門してみました
今回はライブラリを使いましたが仕様を見てスクラッチで開発しても良いかなと思います

よく REST などと比較されますが、ポイントは

  • パスが / のみ
  • リクエストは POST + JSON
  • バッチリクエストができる
  • HTTP 以外のプロトコルでも使える

あたりかなと思います
ユーザ側は関数名だけ知っていればいいのでシンプルなシステム作りに向いているかなと思います
ただライブラリが少ないのと最近は REST が主流になっているイメージもあるのでメインで使われるケースは少ないような気もします
が、ケースによっては JSON-RPC のほうが良い場合もあるのでそこは取捨選択かなと思います

参考サイト

0 件のコメント:

コメントを投稿