你仔细看着两个版本之间的代码,发现一模一样,也没有差异啊。
这就把我干懵逼了:咋回事?说好的差异呢?
别忘了,上面的代码里面是有一个变量的:
换句话说就是:2.7.5 版本之前,业务数据返回后,默认在 IO 线程里面进行反序列化的操作。而2.7.5 版本之后,默认是延迟到客户端线程池里面进行反序列化的操作。
(建议朗读并背诵)
同时这个参数,不管在哪个版本里面,都是可以配置。虽然基本上也没有人更改过这个配置,配置方法如下:
朋友们,到这里还跟的上不?跟不上你就再捋捋?别硬看,伤身体。
解码操作源码解析
接下来我们再看看解码操作的代码到底是怎么样的。
首先解码操作,解的什么码?
解的是响应报文的响应体,也就是我们的返回内容:
org.apache.dubbo.rpc.protocol.dubbo.DecodeableRpcResult#decode(org.apache.dubbo.remoting.Channel, java.io.InputStream)
因为 IO 线程和客户端线程池都要调用这个方法进行解码,我们总不能解码两次吧,那怎么保证只解码一次呢?
答案就是设置标识位。
因为我们知道如果是在 IO 线程里面解码,那么该操作调用解码方法后,肯定是先于客户端线程池调用的。
有先后顺序就好办了。我们就可以设置标识位:
这样也解释了,为什么说是“延迟”到客户端线程池里面解码。
好了,到这里你有没有发现一个问题。前面解析的这么多源码,然后咔一下,直接我们就看到了最终返回的“Hello why”了。
这个是响应消息体,是 body。
头呢?header 呢?
别急,这不是马上就给你讲一下嘛。
前面讲这个方法的时候说了:header 是作为参数传进来的嘛,那我们还可以去找一下 header 到底是怎么传进来的:
怎么看呢?
顺着调用链往回找就行,一个调试小技巧,送给大家,不客气:
可以看到 header 是从 buffer 里面取出来的,最多读
取 HEADER_LENGTH (16) 个字节。
什么?你还问我为什么最多读 16 个字节?
我怀疑前面讲协议的时候你就在走神。别问,问就是协议规
定。大家遵守就好了。
再跟着调用链往前一步,你会发现这里主要是在做解码响应头的部分: