Dubbo协议解析

Dubbo协议设计参考了TCP/IP协议,包括协议头和协议体两部分。16字节报文头主要携带了魔法数(0xdabb,用于分割两个不同请求),以及当前请求报文是否是Request、Response、心跳和事件的信息,请求时也会携带当前报文体内序列化协议编号,另外还有请求状态、请求唯一表示和报文体长度。

0~7           魔数高位   存储0xda
         8~15         魔数低位   存储0xbb
         16             数据包类型   是否为双向的RPC调用(比如方法调用有返回值),0位Response,1位Request
         17             调用方式    16位为1的情况下有效,0为单向调用,1为双向调用
         18             事件标识     0为请求/响应包,1位心跳包
         19~23       序列化器编号
         24~31       状态
         32~95       请求编码     8个字节存储RPC请求的唯一id,用来将请求和响应做关联
         96~127     消息体长度     4个字节消息体,存有Dubbo版本号、服务接口名、服务接口版本、方法名、参数类型、方法参数值和请求额外参数

Netty编解码器扩展

Netty提供了两个基类,一个是ByteToMessageDecoder解码基类,一个是MessageToByteEncode编码基类,用于自定义协议扩展。

ByteToMessageDecoder

ByteToMessageDecoder是一个抽象类,解码方法名decode,需要子类去实现。继承关系如下图:

ByteToMessageDecoder继承了ChannelInboundHandlerAdapter,是一个Inbound入站处理器,关于ChannelPipeline事件传播机制前面几篇文章已经做了详细介绍,此处不再赘述,所以重点关注一下其channelRead方法,即读事件的传播,代码如下:

其实现比较简单,主要是对ByteBuf解码,然后继续向下传播ChannelRead事件,解码具体实现在callDecode方法中,代码实现如下:

callDecode中会读取数据,然后会调用decodeRemovalReentryProtection继续解码,在decodeRemovalReentryProtection中我们看到了所期待的的调用子类的decode方法解码。

MessageToByteEncoder

与解码器相对的,MessageToByteEncoder编码器,也是个抽象基类,提供了抽象方法encode需要子类去实现,继承关系如下图:

由继承关系图可以看出,MessageToByteEncoder继承了ChannelOutboundHandlerAdapter,是一个outbound出站处理器,重点关注其write方法,代码实现如下:

代码逻辑还是比较清晰,就是调用encode编码,然后向下传播write事件。

到这里就看到了Netty对自定义编解码的扩展,下面介绍Dubbo对扩展的自定义实现。

Dubbo协议实现源码分析

编解码器本质上都是handler,所以先从Netty启动是往ChannelPipeline中添加handler开始看,以服务端为例,NettyServer#doOpen方法代码如下:

标准的一个Netty服务器写法,里边可以看到编解码都由NettyCodecAdapter维护,NettyCodecAdapter代码如下:

实现较为简单,维护了两个内部类,一个是InternalEncoder继承自MessageToByteEncoder,一个是InternalDecoder继承自ByteToMessageDecoder,实现了对应的编解码接口。以及维护了一个Code2类型的对象,Codec2也是一个扩展点,对应不同协议的实现,因为介绍Dubbo协议,所以此处是DubboCountCodec,DubboCountCodec代码如下:

DubboCountCodec内部维护了一个DubboCodec,DubboCodec才是编解码具体实现,DubboCountCodec做的就是一次性读取更多完整报文编解码生成对象。DubboCodec继承关系如下图:

encode源码分析

先介绍encode,DubboCountCodec调用encode之后,其具体实现逻辑位于ExchangeCodec#encode方法,实现代码如下:


         首先对需要编码的消息类型进行判断,如果是Request则调用encodeRequest,如果是Response则调用encodeResponse,如果都不是,则调用父类TelnetCodec的encode方法。先展开分析下encodeRequest方法,代码如下:


         实际上就是对开头所描述的Dubbo协议的构建,其中会调用encodeRequestData对RpcInvocation调用进行编码,代码如下:


         主要是将方法调用参数和值编码成字节流。包括框架版本、调用接口、方法名称、参数类型、参数值等信息。

encodeResponse方法实现与encodeRequest方法实现十分相似,同样是对Dubbo协议字节流的构建,不再展开描述,主要介绍下其encodeResponseData方法,其data一半是Result类型,实现代码如下:


         主要完成对调用结果的序列化。

decode源码分析

解码过程要比编码复杂一点,主要是需要解决粘包和半包问题,其实现位于ExchangeCodec#decode方法,实现代码如下:

解码主要分为解码16字节报文头和解码报文体,具体的消息体解码位于DubboCodec#decodeBody方法中,具体代码如下:

解码分为对request的解码和response的解码,虽然看上去很长,其实只是请求类型的分类,以及根据decode.in.io的配置值判断是在I/O线程中直接解码,还是交由业务线程池去解码。

请求消息解码具体实现位于DecodeableRpcInvocation#decode方法,代码实现如下:

主要逻辑是获取各项参数封装到当前的RpcInvocation对象中。

响应消息解码的具体实现位于DecodeableRpcResult#decode中,具体代码实现如下:

根据响应标记位,对各种情况下的响应做处理,正常情况下将返回数据反序列化后存到result字段中。

Dubbo篇:基于Netty实现Dubbo协议编解码源码分析相关推荐

  1. netty中的future和promise源码分析(二)

    前面一篇netty中的future和promise源码分析(一)中对future进行了重点分析,接下来讲一讲promise. promise是可写的future,从future的分析中可以发现在其中没 ...

  2. 物联网协议之MQTT源码分析(二)

    此篇文章继上一篇物联网协议之MQTT源码分析(一)而写的第二篇MQTT发布消息以及接收Broker消息的源码分析,想看MQTT连接的小伙伴可以去看我上一篇哦. juejin.im/post/5cd66 ...

  3. 基于TCP网络通信的自动升级程序源码分析-客户端接收文件

    升级程序客户端接收文件 /// <summary>/// 文件数据缓存 索引是 ConnectionInfo对象 数据包的顺序号 值是数据/// </summary>Dicti ...

  4. dubbo注册服务IP解析异常及IP解析源码分析

    https://www.cnblogs.com/leo-li-3046/p/5702479.html 在使用dubbo注册服务时会遇到IP解析错误导致无法正常访问. 比如: 本机设置的IP为172.1 ...

  5. wireshark协议解析器 源码分析 封装调用

    源码分析 Wireshark启动时,所有解析器进行初始化和注册.要注册的信息包括协议名称.各个字段的信息.过滤用的关键字.要关联的下层协议与端口(handoff)等.在解析过程,每个解析器负责解析自己 ...

  6. sofa协议服务器,SOFARPC 源码分析1 - 最简使用姿势

    SOFARPC 是一个高性能.高可扩展.生产级别的 RPC 框架,由蚂蚁金服开源. 本文会提供一个 SOFARPC 最简使用示例(使用 SOFARegistry 做注册中心),之后的源码分析都会基于该 ...

  7. 基于XMPP协议的aSmack源码分析

    在研究如何实现Pushing功能期间,收集了很多关于Pushing的资料,其中有一个androidnp开源项目用的人比较多,但是由于长时间没有什么人去维护,听说bug的几率挺多的,为了以后自己的产品稳 ...

  8. 基于后端开发Redisson实现分布式锁源码分析解读

    一.分布式锁的概念和使用场景 分布式锁是控制分布式系统之间同步访问共享资源的一种方式. 在分布式系统中,常常需要协调他们的动作.如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问 ...

  9. [Python-Twisted] 协议基类源码分析。

    学习Twisted时,有时老感觉摸不着边际,虽然说要用什么twisted都给你实现了,但心里总有不踏实之感. 遂从twisted.internet.protocol.Protocol这个所有协议的基类 ...

最新文章

  1. 用 Python 爬了点你们喜欢的小电影
  2. php %3c%3c%3c 解析常量,PHP基础知识小结1
  3. nginx优化25条
  4. SpringBootStarter种类
  5. BZOJ 3489: A simple rmq problem(K-D Tree)
  6. oracle供应商导入,AP供应商导入简例.pdf
  7. mysql data文件夹恢复_【专注】Zabbix源码安装教程—步骤详解(2)安装并配置mysql...
  8. 拖动效果,防止选中文字兼容代码
  9. 将JSON转成DataSet(DataTable)
  10. 金融工程与计算机联系紧密吗,美国留学金融工程专业院校有什么推荐的呢?
  11. 月均数据_月均收入15k的数据产品经理=数据+产品经理?
  12. 判断三个数是否能构成三角形_【内含干货】611. 有效三角形的个数
  13. 蓝桥杯2018年第九届C/C++省赛A组第一题-分数
  14. (8)Linux(客户端)和Windows(服务端)下socket通信实例
  15. JavaScript:获取帧率FrameUtil.js
  16. Java, 基础(面试题)总结(分享-交流)
  17. Spring的AOP实现原理
  18. RGB色彩模式-最广的颜色系统之一
  19. 【HUSTOJ】1047: 字符图形3-平行四边形
  20. 协同感知综述:从异质单体到分层合作

热门文章

  1. MyBatis中的大于号小于号怎么表示
  2. 分享蔡澜老师的自问自答
  3. 华为机试_HJ24 合唱队【中等】【收藏】
  4. 苹果4如何添加时间插件_Pr快速批量制作和添加字幕,节省时间还不用插件的做法...
  5. 黑小米真不应该,如今它已是国货之光,成为国产手机在海外领军者
  6. sql2008数据导入与导出
  7. 给SpringBoot Web应用配上JavaFx漂亮衣服
  8. @Cacheable缓存注解使用
  9. 门限签名(1)——秘密共享
  10. 深井冰!沙雕码农脑洞大,盘点Github上那些不忍直视奇葩脑回路的沙雕项目!