服务端响应编码总体流程:
1 NettyCodecAdapter$InternalEncoder.encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) 2 -->new NettyBackedChannelBuffer(ByteBuf buffer) // 创建一个buffer 3 -->NettyChannel.getOrAddChannel(io.netty.channel.Channel ch, URL url, ChannelHandler handler) 4 -->DubboCountCodec.encode(Channel channel, ChannelBuffer buffer, Object msg) 5 -->ExchangeCodec.encode(Channel channel, ChannelBuffer buffer, Object msg) 6 -->encodeResponse(Channel channel, ChannelBuffer buffer, Response res) 7 -->getSerialization(Channel channel) //获取Hessian2Serialization序列化实例 8 -->CodecSupport.getSerialization(URL url) 9 -->ExtensionLoader.getExtensionLoader(Serialization.class).getExtension(url.getParameter("serialization", "hessian2")) 10 <!-- 构造一个16字节的byte[16] header --> 11 -->byte[] header = new byte[16] 12 -->Bytes.short2bytes(MAGIC, header) //设置前两个字节为魔数[-38, -69, 0, ..., 0] 13 <!-- 第三个字节:序列化协议ID,如果响应是心跳,添加eventFlag --> 14 -->header[2] = serialization.getContentTypeId(); 15 if (res.isHeartbeat()) header[2] |= FLAG_EVENT; 16 <!-- 第四个字节:响应状态 --> 17 -->header[3] = res.getStatus(); 18 <!-- 设置第5~12个字节(long是64bit,即8byte):respID == requestID --> 19 -->Bytes.long2bytes(res.getId(), header, 4); 20 <!-- 下面序列化响应体数据 --> 21 -->new Hessian2ObjectOutput(out) 22 -->DubboCodec.encodeResponseData(Channel channel, ObjectOutput out, Object data) 23 -->Bytes.int2bytes(len, header, 12); // 设置第13~16个字节(int是32位,4个字节):消息体长度 24 -->buffer.writeBytes(header); // 将header写入buffer的前16位
与 12.1 客户端请求编码 极其相似。
注意:响应编码中DubboCodec
1 @Override 2 protected void encodeResponseData(Channel channel, ObjectOutput out, Object data) throws IOException { 3 Result result = (Result) data; 4 5 Throwable th = result.getException(); 6 if (th == null) { 7 Object ret = result.getValue(); 8 if (ret == null) { 9 out.writeByte(RESPONSE_NULL_VALUE); 10 } else { 11 out.writeByte(RESPONSE_VALUE); 12 out.writeObject(ret); 13 } 14 } else { 15 out.writeByte(RESPONSE_WITH_EXCEPTION); 16 out.writeObject(th); 17 } 18 }
注意:out.writeByte(RESPONSE_VALUE);写入这个响应类型,是为了将来客户端响应解码用的,具体见 12.4 客户端响应解码
请求编码的byte[] header的最终结构:
- 1~2 byte:魔数
- 3 byte:requestFlag、序列化方式ID、twowayFlag或eventFlag
- 5~12 byte :requestID
- 13~16:请求体长度
响应编码的byte[] header的最终结构:
- 1~2 byte:魔数
- 3 byte:序列化方式ID、eventFlag(如果响应信息是心跳信息,添加eventFlag)
- 4 byte:响应状态,20代表成功
- 5~12 byte :reponseID(实际上==requestID)
- 13~16:响应体长度