AnyEvent::MPRPC から MessagePack-RPC Java の接続
2011/08/08 追記
AnyEvent::MPRPC を修正して頂いた。ver 0.10 では解消済み。
Perl の AnyEvent::MPRPC::Client を使用して MessagePack-RPC Java サーバに接続した際にメソッドコールを行っても何もデータが応答がない。
クライアント側の実装。
#!/usr/bin/env perl use strict; use warnings; use AnyEvent::MPRPC::Client; use Data::Dumper; my $client = AnyEvent::MPRPC::Client->new( host => '127.0.0.1', port => 1985 ); my $d = $client->call('echo', ['foo bar']); my $res; eval { $res = $d->recv }; if (my $error = $@) { warn Dumper $error; } warn Dumper $res;
サーバ側。
package jp.heavenshell import org.msgpack.rpc.Server; import org.msgpack.rpc.loop.EventLoop; public class ServerApp { public String echo(String msg) { System.out.println(msg); return "hello " + msg; } public static void main(String[] args) { EventLoop loop = EventLoop.defaultEventLoop(); Server svr = new Server(); svr.serve(new ServerApp()); try { svr.listen(1985); loop.join(); } catch (Exception e) { e.getStackTrace(); } } }
で、MessagePack-RPC Java のソースを Eclipse からデバッグ実行をしてみた。
src/main/java/org/msgpack/rpc/transport/RpcMessageHandler.java の handleMessageImpl(MessageSendable channel, MessagePackObject msg) メソッド内にブレークポイントを張って実行する。
private void handleMessageImpl(MessageSendable channel, MessagePackObject msg) { MessagePackObject[] array = msg.asArray(); // TODO check array.length int type = array[0].asInt(); if(type == Messages.REQUEST) { // REQUEST int msgid = array[1].asInt(); String method = array[2].asString(); MessagePackObject args = array[3]; handleRequest(channel, msgid, method, args); } else if(type == Messages.RESPONSE) { //-snip- }
ここの int msgid = array[1].asInt(); にステップオーバした瞬間に落ちた。
array の中に何が入っているかデバッグ実行で表示したら以下の様な値が入っている。
array MessagePackObject[4] [0] ShortIntegerTypeIMPL [1] RawType [2] RawType [3] ArrayType
これをクライアントが Python の場合以下の場合のようになった。
array MessagePackObject[4] [0] ShortIntegerTypeIMPL [1] ShortIntegerTypeIMPL [2] RawType [3] ArrayType
MessagePack-RPC の Request の Spec は以下の用に定義されている。
msgid
The 32-bit unsigned integer number. This number is used as a sequence number. The server replies with a requested msgid.
http://wiki.msgpack.org/display/MSGPACK/RPC+specification#RPCspecification-RequestMessage
というわけで [1] に RawType が来ているのが原因っぽい。
Data::MessagePack には Pure Perl の実装があって、$ENV{PERL_ONLY} で判定しているので、export PERL_ONLY=pp として実行すると、[1] ShortIntegerTypeIMPL となって結果が正しく取得できた。
$ export PERL_ONLY=pp $ perl client.pl hello foo bar
ということで Data::MessagePack の XS 実装が怪しいことまでわかった。