dubbo系列之网络通信编码解码-consumer响应结果编码
简要
在收到provider返回的编码数据后,consumer要进行解码,这时候可能会出现粘包和拆包的问题。
源码解析
NettyCodecAdapter.InternalDecoder类
messageReceived()
分两个部分
1 | //首先判断当前decoder对象的buffer中是否有可以读取的消息,若有,则合并。并将对象赋值给message局部变量 |
1 | try { |
DubboCountCodec类
decode()
1 | public Object decode(Channel channel, ChannelBuffer buffer) throws IOException { |
这里暂存了当前buffer
的读索引,同样也是为了后面的回滚。可以看到当decode返回的是NEED_MORE_INPUT则表示当前的buffer
中数据不足,不能完整解析出一个dubbo协议栈,同时将buffer的读索引回滚到之前暂存的索引并且退出循环,将结果返回。
为什么这里有一个死循环?
接着往下看
ExchangeCodec类
decode()
1 | protected Object decode(Channel channel, ChannelBuffer buffer, int readable, byte[] header) throws IOException { |
针对包含一个以上的dubbo协议栈,当然也会解析出其中一个dubbo协议栈,但是经过ExchangeCodec
解析之后,message
的readIndex不在message
尾部,所以message
的readable
方法返回的是true
。那么则会继续遍历message
,读取下面的信息。最终要么message
刚好整数倍包含完整的dubbo协议栈,要不ExchangeCodec
返回NEED_MORE_INPUT
,最后将未读完的数据缓存到buffer
中,等待下次inbound事件,将buffer
中的消息合并到下次的inbound消息中,种类又回到了拆包的问题上。
##总结
dubbo在处理tcp的粘包和拆包时是借助InternalDecoder
的buffer
缓存对象来缓存不完整的dubbo协议栈数据,等待下次inbound事件,合并进去。所以说在dubbo中解决TCP拆包和粘包的时候是通过buffer
变量来解决的
上面的方法就解决了粘包了拆包的问题了
若出现粘包,就会根据它的请求长度进行截取;
若出现拆包,数据会不完整,就进入循环重新读取,直到取到完整数据。
接着往里看看
DubboCodec类
1 | protected Object decodeBody(Channel channel, InputStream is, byte[] header) throws IOException { |
DecodeableRpcResult类
decode()——根据RESPONSE_NULL_VALUE RESPONSE_VALUE RESPONSE_WITH_EXCEPTION进行相应的处理
1 | public Object decode(Channel channel, InputStream input) throws IOException { |