Dubbo网络通讯协议
1. 前言
前面已经分析了Dubbo是如何暴露以及引用远程服务的,接下来自然是服务调用的实现细节了,但是在那之前,有必要先了解Dubbo的网络通信协议。
在单机系统中,调用本地方法获取结果很简单,因为同一个进程里内存是共享的。但是在分布式系统中,远程方法调用就显得较为复杂,必须通过网络将内存中的数据传输给对方,数据以何种格式传输呢?这就需要双方约定一个协议。
2. 通讯协议细节
这是Dubbo官方文档给的图,可以看出协议主要分为两块:16字节定长的Header、变长的Body。
2.1 协议头和协议体
Dubbo通讯协议头Header由16字节组成,Header设计的非常紧凑,能用bit表示就绝不用byte,内容如下:
Bit | 字段 | 说明 |
---|---|---|
0~15 | Magic Number | 魔数,固定0xdabb |
16 | Req/Res | 0=Response,1=Request |
17 | 2Way | 仅在Request在有用。是否期望服务器返回数据 |
18 | Event | 是否事件信息,如心跳 |
19~23 | Serialization ID | 序列化类型ID |
24~31 | Status | 响应状态 |
32~95 | Request ID | 请求唯一标识 |
96~127 | Data Length | Body的长度 |
变长部分 | Body | 对象序列化的byte[] |
Body部分是变长的,长度DataLength已经写在Header里了。Dubbo可以根据DataLength解决TCP粘包/拆包的问题,如果读取的字节数不足16,说明连一个完整的Header都没有接收到,此时会等待对端发送更多的数据。读取到一个完整的Header,会解析出DataLength,然后判断Body是否完整,不完整同样会等待对端传输更多的数据,完整则解析Body进行后续的请求处理。
2.2 编解码和序列化
Dubbo对于请求用Request类描述,对于响应用Response描述。
Dubbo针对协议头Header部分,使用Codec编解码,针对Body部分,使用序列化的方式。
当Consumer向Provider发起RPC调用时,会先创建RpcInvocation对象,再创建Request对象。然后利用NettyClient将数据发送到对端。我们知道,网络传输的总是字节序列,所以Request对象会经过编码再发送,对应的方法是ExchangeCodec#encodeRequest()
,Dubbo会根据协议的格式向Channel先写入Header,再写入Body。
protected void encodeRequest(Channel channel, ChannelBuffer buffer, Request req) throws IOException {// 序列化策略 默认hessian2Serialization serialization = getSerialization(channel);// 协议头Header 16字节byte[] header = new byte[HEADER_LENGTH];// 2字节 魔数Bytes.short2bytes(MAGIC, header);header[2] = (byte) (FLAG_REQUEST | serialization.getContentTypeId());if (req.isTwoWay()) {header[2] |= FLAG_TWOWAY;}if (req.isEvent()) {header[2] |= FLAG_EVENT;}// RequestId 全局自增Bytes.long2bytes(req.getId(), header, 4);int savedWriteIndex = buffer.writerIndex();buffer.writerIndex(savedWriteIndex + HEADER_LENGTH);// 序列化DataChannelBufferOutputStream bos = new ChannelBufferOutputStream(buffer);ObjectOutput out = serialization.serialize(channel.getUrl(), bos);if (req.isEvent()) {encodeEventData(channel, out, req.getData());} else {encodeRequestData(channel, out, req.getData(), req.getVersion());}out.flushBuffer();if (out instanceof Cleanable) {((Cleanable) out).cleanup();}bos.flush();bos.close();int len = bos.writtenBytes();// 校验负载,Body是否太大checkPayload(channel, len);Bytes.int2bytes(len, header, 12);buffer.writerIndex(savedWriteIndex);buffer.writeBytes(header); // write header.buffer.writerIndex(savedWriteIndex + HEADER_LENGTH + len);
}
Provider响应的Response,也是需要编码再发送的,处理流程和Request差不多,这里就不贴代码了。
对于Body部分,RpcInvocation该如何编码呢?我们以DubboCodec为例,事实上Dubbo并不会将整个RpcInvocation对象序列化输出,而是按照固定的格式,将重要信息写入到ObjectOutput。
格式如下:
- 协议Version
- ServiceName
- ServiceVersion
- MethodName
- ParameterTypesDesc
- Arguments序列化
- Attachments序列化
Provider按照约定的格式,依次将这些数据再读取出来即可。
protected void encodeRequestData(Channel channel, ObjectOutput out, Object data, String version) throws IOException {RpcInvocation inv = (RpcInvocation) data;out.writeUTF(version);String serviceName = inv.getAttachment(INTERFACE_KEY);if (serviceName == null) {serviceName = inv.getAttachment(PATH_KEY);}out.writeUTF(serviceName);out.writeUTF(inv.getAttachment(VERSION_KEY));out.writeUTF(inv.getMethodName());out.writeUTF(inv.getParameterTypesDesc());Object[] args = inv.getArguments();if (args != null) {for (int i = 0; i < args.length; i++) {out.writeObject(encodeInvocationArgument(channel, inv, i));}}out.writeAttachments(inv.getObjectAttachments());
}
3. 总结
Dubbo通讯协议分为Header和Body两部分,Header固定由16个字节组成,设计的非常紧凑,尽可能的用bit表示,包含:魔数、请求响应标识、2Way标识、Event标识、序列化ID、Status、RequestID、DataLength。Body则是变长的,长度记录在Header最后4字节里,Dubbo可以基于此来解决TCP的粘包/拆包问题。
Header部分采用Codec编解码,Body部分使用序列化,具体取决于使用的的序列化实现方案,默认是Hessian2。
Dubbo网络通讯协议相关推荐
- 网络编程2_网络通讯协议, socket(tcp, udp)
一. 网络通讯协议 互联网协议的功能: 定义计算机如何接入internet, 以及接入internet的计算机的通信标准 互联网协议按照功能的不同分为osi七层或tcp/ip五层 ...
- 企业即时通讯软件,网络通讯协议和机制怎么选?
一个大型组织如果需要从头开发一套自主可控的即时通讯软件,从技术角度第一个要考虑的核心问题就是:如何确定客户端和服务器之间的通讯协议和通讯机制? 通讯协议怎么选? 大型组织架构就意味着员工人数多,网络情 ...
- TCP/IP 中文译名为传输控制协议/因特网互联协议,又叫网络通讯协议
原文地址:http://hi.baidu.com/albyuyrgqgbbhoq/item/65006d2d002ab33195f62ba1 TCP/IP(Transmission Control P ...
- 如何通过序列化在网络间传递对象,网络协议:轻松定义自己的网络通讯协议
//每次编写设计网络通讯程序时,总面对一个问题,就是要自定义一组应用协议(即通讯协议),然后再写相应的方法来解析协议,并提供相应的接口供上层调用.假如只是简单的文本信息通讯还轻易,但要交换一些控制信息 ...
- html网络通信协议设计,智能家居无线网络通讯协议设计方案
"智能家居"(smart home)又称智能住宅,它利用先进的计算机技术.嵌入式系统技术.网络通讯技术与传感器技术等,把家中的各种设备有机的结合起来,优化用户生活方式,方便用户管理 ...
- 通讯协议,网络通讯协议基本原理透析
文章目录 通讯协议 TCP/IP协议 TCP/IP模型 osi版 基本版 应用层 传输层 网络层 数据链层 物理层 通讯协议 我们想要进⾏数据通讯分⼏步? 1.找到对⽅ip 2 .数据要发送到对⽅指定 ...
- 游戏开发中网络通讯协议对比
在网络游戏开发中,通讯协议是一个无法被避免的问题,无论对于客户端开发中还是服务器开发程序猿而言,制定一个合适的通讯协议是很有必要的 游戏联网需求有弱联网游戏,即时互动类游戏 选择通讯协议的时候主要关注 ...
- 几种网络通讯协议(WIFI,WAPI,GSM,GPRS,CDMA)概述
什么是WIFI WIFI全称Wireless Fidelity,又称802.11b标准,它的最大优点就是传输速度较高,可以达到11Mbps,另外它的有效距离也很长,同时也与已有的各种 802.11 D ...
- 【转载】网络通讯协议的国际斗争
图片发自简书App
最新文章
- 下面算法中,不属于公开密钥加密算法的是()。D
- day002-HTML知识点总结:浏览器兼容性之指定IE浏览器使用chrome内核渲染页面
- python基本数据类型及操作
- lex/flex 笔记
- CSDN:借助工具对【本博客访问来源】进行数据图表可视化(网友主要来自美国、新加坡、日本、英德加澳等)——记录数据来源截止日期20200718晚上22点
- 跟小段一起学Solaris(20)---ipFilter防火墙
- 线上环境部署MongoDB的官方建议
- SAP Spartacus table里显示较长数据时自动显示省略号的设置
- Fiddler抓包 | 竟然有这些骚操作,太神奇了?
- MobileNet-v3详解
- centos7 搭建本地git_小白也能看懂,30 分钟搭建个人博客!
- curl get请求_PHP 请求该用 cURL 还是 Guzzle ?
- 远程控制多台服务器,perl远程执行多台服务器shell命令
- 如何修改(显示)文本文档后缀名
- 惯性系统常用坐标系_惯性坐标系与非惯性坐标系
- Python-struct
- SFP光模块接口说明
- Uipath Try Catch 妙用
- 半监督学习之伪标签(pseudo label,entropy minimization,self-training)
- 三年上一大台阶,联想凌拓做对了什么?
热门文章
- package architecture (amd64) does not match system (arm64)
- Tokenizer和Split
- 如何将VMWare Workstation 虚拟机文件导入到ESX Server——VMX 转成 OVF 格式
- 十、MyBatis的缓存
- 小明和小强都是张老师的学生,张老师的生日是M月N日
- LibQQt系列之十六《QQt版本划分》
- JAVA 注册 HUANXIN 即时通信
- windows server 2003 复制其他电脑的文件到服务器,访问windows server 2003共享文件夹特别慢...
- 如何学习BCGControlBar?
- 软件工程基础个人项目——数独终局生成求解