前提
最近在看Netty相关的资料,刚好SOFA-BOLT是一个比较成熟的Netty自定义协议栈实现,于是决定研读SOFA-BOLT的源码,详细分析其协议的组成,简单分析其客户端和服务端的源码实现。
- 吐槽一下:SOFA-BOLT的代码缩进和FastJson类似,变量名称强制对齐,对于一般开发者来说看着源码会有不适感
当前阅读的源码是2021-08左右的SOFA-BOLT仓库的master分支源码。
SOFA-BOLT简单介绍
SOFA-BOLT是蚂蚁金融服务集团开发的一套基于Netty实现的网络通信框架,本质是一套Netty私有协议栈封装,目的是为了让开发者能将更多的精力放在基于网络通信的业务逻辑实现上,而不是过多的纠结于网络底层NIO的实现以及处理难以调试的网络问题和Netty二次开发问题。SOFA-BOLT的架构设计和功能如下:
❝
上图来源于SOFA-BOLT官网
https://www.sofastack.tech/projects/sofa-bolt/overview❞
SOFA-BOLT协议透视
由于SOFA-BOLT协议是基于Netty实现的自定义协议栈,协议本身的实现可以快速地在Encoder和Decoder的实现中找到,进一步定位到com.alipay.remoting.rpc包中。从源码得知,SOFA-BOLT协议目前有两个版本,协议在RpcProtocol和RpcProtocolV2的类顶部注释中有比较详细的介绍,基于这些介绍可以简单整理出两个版本协议的基本构成。
V1版本协议的基本构成
- V1版本的协议请求Frame基本构成:
- V1版本的协议响应Frame基本构成:
针对V1版本的协议,各个属性展开如下:
- 请求Frame和响应Frame的公共属性:
属性Code |
属性含义 |
Java类型 |
大小(byte) |
备注 |
proto |
协议编码 |
byte |
1 |
V1版本下,proto = 1,V2版本下,proto = 2 |
type |
类型 |
byte |
1 |
0 => RESPONSE,1 => REQUEST,2 => REQUEST_ONEWAY |
cmdcode |
命令编码 |
short |
2 |
1 => rpc request,2 => rpc response |
ver2 |
命令版本 |
byte |
1 |
从源码得知目前固定为1 |
requestId |
请求ID |
int |
4 |
某个请求CMD的全局唯一标识 |
codec |
编码解码器 |
byte |
1 |
- |
❝
上表中,codec从字面上理解是编码解码器,实际上是序列化和反序列实现的标记,V1和V2目前都是固定codec = 1,通过源码跟踪到SerializerManager的配置值为Hessian2 = 1,也就是默认使用Hessian2进行序列化和反序列化,详细见源码中的HessianSerializer
❞
- 请求Frame特有的属性:
属性Code |
属性含义 |
Java类型 |
大小(byte) |
备注 |
timeout |
请求超时时间 |
int |
4 |
|
classLen |
请求对象(参数)类型的名称长度 |
short |
2 |
值>=0 |
headerLen |
请求头长度 |
short |
2 |
值>=0 |
contentLen |
请求内容长度 |
int |
4 |
值>=0 |
className bytes |
请求对象(参数)类型的名称 |
byte[] |
- |
|
header bytes |
请求头 |
byte[] |
- |
|
content bytes |
请求内容 |
byte[] |
- |
- 响应Frame特有的属性:
属性Code |
属性含义 |
Java类型 |
大小(byte) |
备注 |
respstatus |
响应状态值 |
short |
2 |
在ResponseStatus中定义,目前内置13种状态,例如0 => SUCCESS |
classLen |
响应对象(参数)类型的名称长度 |
short |
2 |
值>=0 |
headerLen |
响应头长度 |
short |