MessagePack RPC プロトコル
※2010-04-06追記:ここの内容は大体あっていますがもう古いです。MessagePack-RPCプロトコル仕様(ドラフト)と実装例 を参照してください。
名前は(仮)です。
現在クラスタ通信フレームワーク ccf というものを開発中で*1、MessagePack を使ったRPCプロトコルを使っています。プロトコルの仕様は JSON-RPC を元に MessagePack 用により高速性を重視したもので、とてもシンプルです。
1つの通信路(TCPコネクションなど)でRPCの遅延リターンができるように、メッセージにはシーケンス番号が入っています。応答を2回以上返してしまっても片方を無視できたり、RPC応答をRPC要求とは異なる通信路で返すことができるという利点もあります。
RPC要求
RPC要求は次の4つの要素からなる配列 [type, msgid, method, params] です:
- type
- 必ず整数0です。このメッセージがRPC要求であることを示します。
- msgid
- シーケンス番号を示す最大 32bit の符号無し整数です。このRPC呼び出しに対応するRPC応答にも同じ値を入れます。
- method
- 呼び出すメソッドを示す、最大 32bit の符号無し整数か、文字列です。
- params
- メソッドの引数を示す、任意のオブジェクトです。
RPC応答
RPC応答は次の4つの要素からなる配列 [type, msgid, error, result] です。
- type
- 必ず整数1です。このメッセージがRPC応答であることを示します。
- msgid
- このRPC応答が対応しているRPC要求のシーケンス番号です。
- error
- メソッドが正常に実行された場合:nil メソッドがエラーだった場合:nil 以外の任意のオブジェクト
- result
- メソッドの返り値を示す、任意のオブジェクトです。エラーだった場合は普通は nil にするでしょうが、nil でなくても良いでしょう。
ポイント
すべてのRPC要求には応答を返す必要があります。今のところ JSON-RPC にある Notification(応答を要求しないRPC要求)はありません。作るとしたら、RPC要求の msgid を nil にしたものが Notification になると思います。
RPC応答の配列の順番が少々奇妙に思われるかもしれませんが(そうでもない?)、これはサイズが小さくなるであろう要素を先頭にまとめ、一番サイズが大きくなるであろう要素(result)を一番後ろに持ってきた方が都合が良いためです。
MessagePack の特性上、最初にヘッダ([type, msgid, error, ?])だけ write(2) 送って、result は sendfile(2) で送る、といったことが可能です。
*1:ccf は用途的には Thrift と同じ物です。クライアント・サーバー間の通信だけでなく、サーバー・サーバー間の通信も意識しています。