一 RPC协议简介
在一个典型的RPC的使用场景中,包含了服务发现、负载、容错、序列化和网络传输等组件,其中RPC协议指明了程序如何进行序列化和网络传输,也就是说一个RPC协议的实现等于一个非透明的RPC调用。
简单来说,分布式框架的核心是RPC框架,RPC框架的核心是RPC协议。
dubbo 支持的RPC协议列表
名称 | 实现描述 | 连接描述 | 使用场景 |
---|---|---|---|
dubbo | 传输服务: mina, netty(默认), grizzy; 序列化: dubbo, hessian2(默认), java, fastjson。 自定义报文 | 单个长连接NIO;异步传输 | 1.常规RPC调用 2.传输数据量小 3.提供者少于消费者 |
rmi | 传输:java rmi 服务; 序列化:java原生二进制序列化 | 多个短连接; BIO同步传输 | 1.常规RPC调用 2.与原RMI客户端集成 3.可传少量文件 4.不支持防火墙穿透 |
hessian | 传输服务:servlet容器; 序列化:hessian二进制序列化 | 基于Http 协议传输,依懒servlet容器配置 | 1.提供者多于消费者 2.可传大字段和文件 3.跨语言调用 |
http | 传输服务:servlet容器; 序列化:http表单 | 依懒servlet容器配置 | 1、数据包大小混合 |
thrift | 与thrift RPC 实现集成,并在其基础上修改了报文头 | 长连接、NIO异步传输 |
(PS:本文只探讨dubbo协议)
二 协议的基本组成
- IP:服务提供者的地址
- 端口:协议指定开放端口
- 运行服务
(1)netty
(2)mima
(3)rmi
(4)servlet容器(Jetty、Tomcat、Jboss) - 协议报文编码
- 序列化方式
(1)Hessian2Serialization
(2)DubboSerialization
(3)JavaSerialization
(4)JsonSerialization
三 Duboo的RPC协议报文
先看下http协议报文格式
同样,Dubbo也有自己的报文格式
以head+request body或head+response body的形式存在
- head
1标志位:表明是请求还是响应还是事件
2status:表明状态是OK还是不OK - request body
1Dubbo版本号
2接口路径
3接口版本
4方法名称
5参数类型
6参数值 - response body
1结果标志(无结果、有结果、异常)
2结果
协议的编解码过程:
四 源码探究
以明晰编码解码和序列化反序列化为目的探究源码。其实就是如上图所示的协议的编解码过程。
com.alibaba.dubbo.rpc.protocol.dubbo.DubboCodec是很重要的一个类,无论是request还是response,还有编码解码都在这里类进行调度。
DubboCodec:
其中重点关注三个方法
decodeBody():解码(请求或响应)以及序列化和反序列化
encodeRequestData():编码请求(发生在Consumer)
encodeResponseData():编码响应(发生在Provider)
1.编码序列化request
发生在Consumer发请求之前
encodeRequestData()
protected void encodeRequestData(Channel channel, ObjectOutput out, Object data) throws IOException {
RpcInvocation inv = (RpcInvocation)data;
out.writeUTF(inv.getAttachment("dubbo", DUBBO_VERSION));
out.writeUTF(inv.getAttachment("path"));