Dubbo协议模块源码剖析
LD is tigger forever,CG are not brothers forever, throw the pot and shine forever.
Modesty is not false, solid is not naive, treacherous but not deceitful, stay with good people, and stay away from poor people.
talk is cheap, show others the code,Keep progress,make a better result.
Survive during the day and develop at night。
目录
在一个典型RPC的使用场景中,包含了服务发现、负载、容错、网络传输、序列化等组件,其中RPC协议就指明了程序如何进行网络传输和序列化 。也就是说一个RPC协议的实现就等于一个非透明的远程调用实现,如何做到的的呢?。
概 述
协议的组成:
1.地址:服务提供者地址
2.端口:协议指定开放的端口
3.报文编码:协议报文编码 ,分为请求头和请求体两部分。
4.序列化方式:将请求体序列化成对象
Hessian2Serialization、DubboSerialization,JavaSerialization,JsonSerialization,运行服务: 网络传输实现
netty,mina,RMI 服务,servlet 容器(jetty、Tomcat、Jboss)
Dubbo中所支持RPC协议使用:
dubbo 支持的RPC协议列表:
名称 实现描述 连接描述 适用场景
dubbo 传输服务: mina, netty(默认), grizzy序列化: hessian2(默认), java, fastjson自定义报文 单个长连接NIO异步传输 1、常规RPC调用2、传输数据量小3、提供者少于消费者
rmi 传输:java rmi 服务序列化:java原生二进制序列化 多个短连接BIO同步传输
hessian 传输服务:servlet容器序列化:hessian二进制序列化 基于Http 协议传输,依懒servlet容器配置 1、提供者多于消费者2、可传大字段和文件3、跨语言调用
http 传输服务:servlet容器序列化:java原生二进制序列化 依懒servlet容器配置 1、数据包大小混合
thrift 与thrift RPC 实现集成,并在其基础上修改了报文头 长连接、NIO异步传输
协议的配置:
Dubbo框架配置协议非常方便,用户只需要在 provider 应用中 配置*<*dubbo:protocol> 元素即可。
<!--
name: 协议名称 dubbo|rmi|hessian|http|
host:本机IP可不填,则系统自动获取
port:端口、填-1表示系统自动选择
server:运行服务 mina|netty|grizzy|servlet|jetty
serialization:序列化方式 hessian2|java|compactedjava|fastjson
详细配置参见dubbo 官网 dubbo.io
-->
<dubbo:protocol name="dubbo" host="192.168.0.11" port="20880" server="netty"
serialization=“hessian2” charset=“UTF-8” />
TODO 演示采用其它协议来配置Dubbo
dubbo 协议采用 json 进行序列化 (源码参见:com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol*)*
采用RMI协议 (源码参见:com.alibaba.dubbo.rpc.protocol.rmi.RmiProtocol)
采用Http协议 (源码参见:com.alibaba.dubbo.rpc.protocol.http.HttpProtocol.InternalHandler)
netstat -aon|findstr “17732”
序列化比较:
fastjson 文本型:体积较大,性能慢、跨语言、可读性高
fst 二进制型:体积小、兼容 JDK 原生的序列化。要求 JDK 1.7 支持。
hessian2 二进制型:跨语言、容错性高、体积小
java 二进制型:在JAVA原生的基础上 可以写入Null
compactedjava 二进制型:与java 类似,内容做了压缩
nativejava 二进制型:原生的JAVA 序列化
kryo 二进制型:体积比hessian2 还要小,但容错性 没有hessian2 好
RPC协议报文编码与实现详解
RPC 传输实现:
RPC的协议的传输是基于 TCP/IP 做为基础使用Socket 或Netty、mina等网络编程组件实现。但有个问题是TCP是面向字节流的无边边界协议,其只管负责数据传输并不会区分每次请求所对应的消息,这样就会出现TCP协义传输当中的拆包与粘包问题。
我们知道tcp是以流动的方式传输数据,传输的最小单位为一个报文段(segment)。tcp Header中有个Options标识位,常见的标识为mss(Maximum Segment Size)指的是,连接层每次传输的数据有个最大限制MTU(Maximum Transmission Unit),一般是1500比特,超过这个量要分成多个报文段,mss则是这个最大限制减去TCP的header,光是要传输的数据的大小,一般为1460比特。换算成字节,也就是180多字节。
tcp为提高性能,发送端会将需要发送的数据发送到缓冲区,等待缓冲区满了之后,再将缓冲中的数据发送到接收方。同理,接收方也有缓冲区这样的机制,来接收数据。这时就会出现以下情况:
1.应用程序写入的数据大于MSS大小,这将会发生拆包。
2.应用程序写入数据小于MSS大小,这将会发生粘包。
3.接收方法不及时读取套接字缓冲区数据,这将发生粘包。
拆包与粘包解决办法:
1.设置定长消息,服务端每次读取既定长度的内容作为一条完整消息。
2.{“type”:“message”,“content”:“hello”}\n
3.使用带消息头的协议、消息头存储消息开始标识及消息长度信息,服务端获取消息头的时候解析出消息长度,然后向后读取该长度的内容。
Dubbo 报文格式
Dubbo协议的编解码过程:
分析:
小结:
参考资料和推荐阅读
1.链接: link.