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 と同じ物です。クライアント・サーバー間の通信だけでなく、サーバー・サーバー間の通信も意識しています。