当前位置: 首页 > news >正文

dubbo源码学习2-dubbo协议源码分析

协议(Protocol)的概念
协议(Protocol)是指在计算机通信或网络交互中,双方事先约定好的规则和标准,用于规范数据如何打包、传输、接收和解释。

所以简单说就是规则,发送数据编码的规则,接收数据解码的规则

Dubbo中的协议
在Dubbo框架中,协议特指RPC(远程过程调用)的通信协议,主要包括:

Dubbo协议:Dubbo默认的自定义二进制协议,基于TCP长连接,二进制头部+序列化体,支持请求-响应模式

dubbo 协议数据包格式
dubbo协议的一个完整的数据包分为消息头和消息体
消息头的长度是 16 字节,在消息头中分为5段内容
magic:占用2个字节,第一个字节值默认是 -38,第二个字节值默认是 -69
flag: 占用一个字节,位于消息头第三位
status: 占用一个字节,位于消息头第4为
request id: 占用8个字节,位于消息头第5-11位,请求Id是一个 long 类型
data length: 占用4个字节,位于消息头最后4为,长度是一个int类型
在这里插入图片描述
以如下消息头为例,flag 是需要转为 8 位的二进制数据进行解析的
status 位值为0,是因为这是一个请求报文,status 仅在响应时有效,表示响应状态,20-OK,30-CLIENT_TIMEOUT,31-SERVER_TIMEOUT等
在这里插入图片描述
关于 flag 的分析

  • 第0位:表示请求/响应标志(1-请求,0-响应)
  • 第1位:是否为双向通信(1-是,0-否)
  • 第2位:是否为事件消息(如心跳事件)
  • 第3-7位:序列化类型编号

消息头分析完了,接下来我们根据源码来分析
dubbo是基于Netty通信的,在dubbo服务启动时,会初始化Netty的线程模型,设置了编解码器类型
InternalDecoder ( 解码器 ) 接收数据时用到
InternalEncoder ( 编码器 ) 发送数据时用到
NettyServerHandler Netty消息处理器
在这里插入图片描述
在接收到数据进行解码时,会通过

int saveReaderIndex = message.readerIndex();

记录当前读取位置,如果读取到的 msg 是Codec2.DecodeResult.NEED_MORE_INPUT 时,表示需要更多数据,则会通过重置读取数据的位置,防止出现半包问题

message.readerIndex(saveReaderIndex);

在这里插入图片描述
在 ExchangeCodec 中定义了消息头的长度为16,并且读取了消息头到 byte[] 中
在这里插入图片描述
在 ExchangeCodec 中还会执行以下步骤

  • 检查magic值,检查高位是否等于 -38,低位是否等于 -69,在dubbo中,这两个值是固定的
  • 如果可读数据长度小于16,则返回需要更多数据
  • 从消息头中,从12位开始读取一个int 值为消息体长度,一个int 为4字节,刚好是消息头的最后4位
  • 如果可读数据小于消息体长度加消息头长度,则返回需要更多数据

在 dubbo中从消息头读取消息长度,再读取对应长度的消息体是解决TCP 粘包问题的关键所在

在这里插入图片描述
读取消息头的第2位,为 flag,在这里 flag 多处做位运算

  • 从 flag 计算出协议类型 proto
  • 计算消息类型是 请求类型还是响应类型
  • 如果是响应类型,判断是否是Response.OK
  • 如果是请求类型,判断是否是双向包
  • 从 proto 中可知是心跳类型还是普通消息类型
    在这里插入图片描述
    如果是请求类型时,使用 DecodeableRpcInvocation 解码实际的消息体
    如果是响应类型时,使用 DecodeableRpcResult 解码实际的消息体
    在这里插入图片描述
    在消息的编解码处理完成之后,解码后的消息体会交给 NettyServerHandler 进行处理,NettyServerHandler则是dubbo接入服务的范围了

执行流程可以参考

dubbo源码学习1-服务提供方接入执行源码分析

http://www.dtcms.com/a/267793.html

相关文章:

  • C++:编译QXlsx库过程
  • 咕咚运动启动时弹出广告
  • Go语言--语法基础6--基本数据类型--切片类型
  • 【学习篇】SQL复杂查询学习
  • D3 面试题100道之(61-80)
  • React 英语单词消消乐一款专为英语学习设计的互动式记忆游戏
  • Flink ClickHouse 连接器:实现 Flink 与 ClickHouse 无缝对接
  • Scala 简介
  • 探索实现C++ STL容器适配器:优先队列priority_queue
  • 三维目标检测|Iou3D 代码解读一
  • [Qt] visual studio code 安装 Qt插件
  • AI(学习笔记第四课) 使用langchain进行AI开发 load documents(pdf)
  • excel 工作需要会的
  • C++:编译QCustomPlot源码为链接库
  • 【MoE】Buffer Overflow in Mixture of Experts
  • [netty5: WebSocketFrameEncoder WebSocketFrameDecoder]-源码解析
  • QML与C++交互之创建自定义对象
  • 使用PyTorch实现Softmax回归(Mnist手写数字识别)
  • Altium Designer使用入门(非精通)教程 第二章(原理图绘制)
  • Windows内核并发优化
  • 比较两个csv文件的内容是否一致
  • 隐马尔可夫模型(HMM):观测背后的状态解码艺术
  • [01背包]494.目标和
  • SQL128 统计2021年未完成试卷作答数大于1的有效用户
  • Mybatis-Plus使用
  • 基于大模型建设的AI智能报表系统
  • Day05:Python中的并发和并行(3)
  • speech_sambert-hifigan_tts_zh-cn_16k的docker部署
  • 【电赛培训】运算放大器、滤波器
  • 关于 JNI 函数逆向(从 Java 到 native)