1、使用kryo序列化
1.1、先升级消费者
dubbo服务接口新增返回值和方法,消费者先升级,调用服务报错:
1 | Caused by: com.alibaba.dubbo.remoting.RemotingException: Fail to decode request due to: RpcInvocation [methodName=dataGrid, parameterTypes=[class com.xxx.ProductInfoDTO, null], arguments=null, attachments={dubbo=2.8.4, input=463, path=com.xxx.product.ProductService, version=0.0.0}] |
1.2、先升级生产者
dubbo服务接口新增返回值和方法,生产者先升级,消费者调用服务报错:
消费者报错:
1 | Caused by: com.alibaba.dubbo.remoting.RemotingException: Fail to decode request due to: RpcInvocation [methodName=dataGrid, parameterTypes=[class com.xxx.ProductInfoDTO, null], arguments=null, attachments={dubbo=2.8.4, input=462, path=com.xxx.ProductService, version=0.0.0}] |
生产者报错:
1 | 2016-10-15 14:54:35,787 [New I/O worker #12] WARN in [com.alibaba.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation.decode(DecodeableRpcInvocation.java:120)] - [DUBBO] Decode argument failed: com.esotericsoftware.kryo.KryoException: Unable to find class: #path, dubbo version: 2.8.4, current host: 172.22.23.214 java.io.IOException: com.esotericsoftware.kryo.KryoException: Unable to find class: #path at com.alibaba.dubbo.common.serialize.support.kryo.KryoObjectInput.readObject(KryoObjectInput.java:127) at com.alibaba.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation.decode(DecodeableRpcInvocation.java:116) at com.alibaba.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation.decode(DecodeableRpcInvocation.java:74) at com.alibaba.dubbo.rpc.protocol.dubbo.DubboCodec.decodeBody(DubboCodec.java:138) at com.alibaba.dubbo.remoting.exchange.codec.ExchangeCodec.decode(ExchangeCodec.java:134) at com.alibaba.dubbo.remoting.exchange.codec.ExchangeCodec.decode(ExchangeCodec.java:95) at com.alibaba.dubbo.rpc.protocol.dubbo.DubboCountCodec.decode(DubboCountCodec.java:46) at com.alibaba.dubbo.remoting.transport.netty.NettyCodecAdapter$InternalDecoder.messageReceived(NettyCodecAdapter.java:134) at org.jboss.netty.channel.SimpleChannelUpstreamHandler.handleUpstream(SimpleChannelUpstreamHandler.java:70) at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:564) at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:559) at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:268) at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:255) at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:88) at org.jboss.netty.channel.socket.nio.AbstractNioWorker.process(AbstractNioWorker.java:109) at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:312) at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:90) at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178) at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108) at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:745) Caused by: com.esotericsoftware.kryo.KryoException: Unable to find class: #path at com.esotericsoftware.kryo.util.DefaultClassResolver.readName(DefaultClassResolver.java:138) at com.esotericsoftware.kryo.util.DefaultClassResolver.readClass(DefaultClassResolver.java:115) at com.esotericsoftware.kryo.Kryo.readClass(Kryo.java:641) at com.esotericsoftware.kryo.Kryo.readClassAndObject(Kryo.java:752) at com.alibaba.dubbo.common.serialize.support.kryo.KryoObjectInput.readObject(KryoObjectInput.java:125) ... 22 more Caused by: java.lang.ClassNotFoundException: #path at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1387) at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1233) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:274) at com.esotericsoftware.kryo.util.DefaultClassResolver.readName(DefaultClassResolver.java:136) ... 26 more |
消费方也升级之后,则可以正常调用服务。
2、使用Hessian2序列化
2.1、先升级消费者
dubbo服务接口新增返回值和方法,消费者先升级,服务可以正常调用,读取接口新增的值也正常,返回为空。
2.2、先升级生产者
dubbo服务接口新增返回值和方法,生产者先升级,消费者调用服务正常。
3、序列化协议切换
测试发现,在版本一直的情况,生产者使用kryo,消费者使用hessian2,或者生产者使用hessian2,消费者使用kryo,都可以正常调同,所以在版本一致的情况可以和好对生产者和服务者的序列化协议进行切换。
4、关于序列化性能对比
总结
可以发现,使用kryo协议,无法保证接口返回值添加属性时升级过程中的兼容,而hessian则可以兼容。
Kryo平均响应时长,每秒事务数,带宽节省等相对来说,的确是比较出众,当Kryo在Dubbo中应用足够成熟之后,使用其作为序列化的确是一个不错的选择。