先来看看一段dubbo调用代码:
ProviderdemoService= (Provider) context.getBean("demoService1");
Test t=new Test();
t.s="hello world";
t.n=1111;
t.l=2222222222l;
String message = demoService.build(t);
dubbo框架底层编码是在DubboCodec的
@Override
protected void encodeRequestData(Channel channel, ObjectOutput out,Object data) throws IOException {
RpcInvocation inv = (RpcInvocation) data;
out.writeUTF(inv.getAttachment(Constants.DUBBO_VERSION_KEY,DUBBO_VERSION));
out.writeUTF(inv.getAttachment(Constants.PATH_KEY));
out.writeUTF(inv.getAttachment(Constants.VERSION_KEY));
out.writeUTF(inv.getMethodName());
out.writeUTF(ReflectUtils.getDesc(inv.getParameterTypes()));
Object[] args = inv.getArguments();
if (args != null)
for (inti = 0; i < args.length; i++) {
out.writeObject(encodeInvocationArgument(channel, inv, i));
}
out.writeObject(inv.getAttachments());
}
Debug下inv的参数看看
RpcInvocation [methodName=build, parameterTypes=[classcom.test.impl.Test], arguments=[com.test.impl.Test@7b0fae4e],attachments={path=com.test.Provider, interface=com.test.Provider,version=0.0.0, timeout=5000}]
包数据=dubbo版本号+接口名称+接口版本号+方法名+参数类型+参数值+ attachments
通过网络抓包,左边的是二进制数据,右边是抓包工具解析出来的数据,windows抓包工具使用wireshark,linux使用tcpdump命令
字符串 “com.test.Provider”用二进制是怎么表示的?dubbo支持多种编解码方式,默认是Hessian2编解码,那就要看Hessian2ObjectOutput.writeUTF的实现。
大概逻辑如下:
String类型的byte编码=length(int类型)+String转为byte
com.test.Provider的长度为17,转为十六进制是11,
‘c’转为byte为十六进制53,同样其他字符逐个转为byte排在后面
11 63 6f 6d 2e 74 65 73 74 2e 50 72 6f 76 69 64 65 72