首页 > 其他分享 >Dubbo Remoting模块详解

Dubbo Remoting模块详解

时间:2023-03-07 22:31:34浏览次数:53  
标签:Dubbo Endpoint Remoting ChannelHandler 接口 Client Channel Transporter 详解

1 Dubbo 整体架构设计

dubbo-remoting 模块提供多种客户端和服务端通信功能。最底层部分即为 Remoting 层:

Dubbo Remoting模块详解_Endpoint

包括 Exchange、Transport和Serialize 三层。本文主要描述 Exchange 和 Transport 两层。

Dubbo直接集成已有的第三方网络库,如Netty、Mina、Grizzly 等 NIO 框架:

Dubbo Remoting模块详解_Endpoint_02

dubbo-remoting-zookeeper使用 Apache Curator 实现与 zk 的交互。

2 dubbo-remoting-api

是其他 ​​dubbo-remoting-*​​ 模块的顶层抽象,其他 dubbo-remoting 子模块都是依赖第三方 NIO 库,来实现 dubbo-remoting-api 模块。

2.1 buffer 包

Dubbo Remoting模块详解_Server_03

Dubbo Remoting模块详解_数据_04

定义Buffer相关接口、抽象类及实现类。在各 NIO 框架中都有自己的缓冲区实现。但这里的 buffer 包在更高层面,抽象各个 NIO 框架的缓冲区,同时也提供一些基础实现。

2.2 exchange包

抽象 Request、Response,并为其添加很多特性。整个远程调用的核心部分。

2.3 transport包

抽象网络传输层,但只负责抽象单向消息传输,即:

  • 请求消息由 Client 端发出,Server 端接收
  • 响应消息由 Server 端发出,Client端接收

很多网络库可实现网络传输,如Netty,transport包是在网络库上层的一层抽象。

2 传输层核心接口

“端点(Endpoint)”:一个 ​​ip​​ 和 ​​port​​ 唯一确定,两端点间会创建 ​​TCP​​ 连接,双向传输数据。

Dubbo 将 Endpoint 之间的 TCP 连接抽象为(Channel)通道:

  • 发起请求的 Endpoint 抽象为Client
  • 接收请求的 Endpoint 抽象为Server

2.1 Endpoint 接口

Dubbo Remoting模块详解_数据_05

  • getXXX() 用于获得 Endpoint 本身的一些属性,如Endpoint 的本地地址、关联的 URL 信息及底层 Channel 关联的 ChannelHandler
  • send() 负责数据发送
  • close() 及 startClose() 用于关闭底层 Channel
  • isClosed() 方法用于检测底层 Channel 是否已关闭

3 Channel

对 Endpoint 双方连接的抽象,就像传输管道。消息发送端往 Channel 写入消息,接收端从 Channel 读取消息。

3.1 接口定义

继承 Endpoint 接口,也具备开关状态以及发送数据能力。可在 Channel 上附加 KV 属性:

Dubbo Remoting模块详解_Server_06

4 ChannelHandler

注册在 Channel 上的消息处理器

4.1 定义

Dubbo Remoting模块详解_数据_07

​@SPI​​ 注解表明该接口是一个扩展点。

有一类特殊的 ChannelHandler 专门负责实现编解码功能,实现:

  • 字节数据与有意义的消息之间的转换
  • 或消息之间的相互转换

Dubbo Remoting模块详解_Endpoint_08

该接口也是个扩展接口,encode()、decode() 被 @Adaptive 注解修饰,也就会生成适配器类,其中会根据 URL 中的 codec 值确定具体的扩展实现类。

DecodeResult 枚举是在处理 TCP 传输时粘包和拆包使用的,如当前能读取到的数据不足以构成一个消息时,就使用 ​​NEED_MORE_INPUT​​ 。

5 Client、RemotingServer

分别抽象客户端、服务端,都继承 Channel、Resetable 等接口,即都具备读写数据的能力。

都继承了 Endpoint,只是在语义上区分请求和响应职责,都具备发送数据能力。

Dubbo Remoting模块详解_数据_09

Client V.S Server

  • Client 只能关联一个 Channel
  • Server 可接收多个 Client 发起的 Channel 连接,所以在 RemotingServer 接口中定义查询 Channel 的相关方法
  • Dubbo Remoting模块详解_数据_10

6 Transporter

Dubbo 在 Client、Server 之上又封装一层Transporter 接口:

Dubbo Remoting模块详解_Server_11

​@SPI​​ 注解扩展接口,默认使用“netty”扩展名。

​@Adaptive​​ 注解表示动态生成适配器类:

  • 先后根据“server”“transporter”的值,确定 RemotingServer 的扩展实现类
  • 先后根据“client”“transporter”的值,确定 Client 接口的扩展实现

几乎对每个支持的 NIO 库,都有接口实现:

Dubbo Remoting模块详解_Endpoint_12

7.1 为何单独抽象Transporter层,不直接让上层使用 Netty?

利用依赖倒置原则,Netty、Mina、Grizzly 等 NIO 库对外接口和使用方式不同,若在上层直接依赖 Netty 或Grizzly,就依赖具体 NIO 库,而非依赖一个有传输能力的抽象,后续要切换实现,就需修改依赖和接入的相关代码。

而有了 Transporter 层,就可通过 Dubbo SPI,修改使用的具体 Transporter 扩展实现,切换到不同 Client 和 RemotingServer 实现,切换底层 NIO 库,而无须修改代码。当有更先进的 NIO 库出现,也只需开发相应的 ​​dubbo-remoting-*​​ 实现模块提供 Transporter、Client、RemotingServer 等核心接口的实现,即可接入,完全符合开放封闭原则。

7 Transporters

不是一个接口,而是门面类,封装:

  • Transporter 对象的创建(通过 Dubbo SPI)
  • 及 ChannelHandler 的处理
public class Transporters {
private Transporters() {
...


public static RemotingServer bind(URL url,
ChannelHandler... handlers) throws RemotingException {
ChannelHandler handler;
if (handlers.length == 1) {
handler = handlers[0];
} else {
handler = new ChannelHandlerDispatcher(handlers);
}
return getTransporter().bind(url, handler);
}



public static Client connect(URL url, ChannelHandler... handlers)
throws RemotingException {
ChannelHandler handler;
if (handlers == null || handlers.length == 0) {
handler = new ChannelHandlerAdapter();
} else if (handlers.length == 1) {
handler = handlers[0];
} else { // ChannelHandlerDispatcher
handler = new ChannelHandlerDispatcher(handlers);
}
return getTransporter().connect(url, handler);
}



public static Transporter getTransporter() {
// 自动生成Transporter适配器并加载
return ExtensionLoader.getExtensionLoader(Transporter.class)
.getAdaptiveExtension();
}
}

在创建 Client、RemotingServer 时,可指定多个 ChannelHandler 绑定到 Channel,来处理其中传输的数据。Transporters.connect()、bind() 方法都会将多个 ChannelHandler 封装成一个 ChannelHandlerDispatcher 对象。

ChannelHandlerDispatcher 也是 ChannelHandler 接口实现类之一,维护一个 CopyOnWriteArraySet 集,它所有的 ChannelHandler 接口实现都会调用其中每个 ChannelHandler 元素的相应方法。ChannelHandlerDispatcher 还提供增删该 ChannelHandler 集合的相关方法。

8 总结

  • Endpoint 接口抽象“端点”概念,这是所有抽象接口的基础
  • 上层使用方会通过 Transporters 门面类,获取到 Transporter 的具体扩展实现,然后通过 Transporter 拿到相应 Client、RemotingServer 实现,就能建立(或接收)Channel 与远端进行交互
  • 无论 Client、RemotingServer,都会使用 ChannelHandler 处理 Channel 中传输的数据,其中负责编解码的 ChannelHandler 被抽象出为 Codec2 接口。

Transporter 层整体结构图

Dubbo Remoting模块详解_Endpoint_13

参考

标签:Dubbo,Endpoint,Remoting,ChannelHandler,接口,Client,Channel,Transporter,详解
From: https://blog.51cto.com/u_11440114/6106516

相关文章

  • 详解第一个程序:程序框架、printf、出错怎么办
    程序框架:在最开始学习的时候没必要理解每一句,只需要知道我们的程序都是在框架之内执行的就可以了。 字符串:字符包括数字、字母和汉字等,串就是它们连成一串。  ......
  • 【选择排序算法详解】Java/Go/Python/JS/C 不同语言实现
    【选择排序算法详解】Java/Go/Python/JS/C不同语言实现 说明选择排序(SelectionSort)是一种简单直观的排序算法。跟冒泡、插入排序一样,它将数列分为已排序和待排序两个......
  • 三大主流平台开发桌面程序的七大优劣势详解
    三大主流平台开发桌面程序的七大优劣势详解2023-03-0114:19·工控自动化编程软件开发环境QT,MFC,WPF等相关的对比详解嗨,大家好,我是兆千图网络科技,很高兴站在这里跟大家分......
  • 串口通信原理详解232、422、485,入门必看!
    串口通信原理详解232、422、485,入门必看!混说Linux ​关注他 53人赞同了该文章本文介绍了串口通讯的基本概念、数据格式、通讯方式、典型的串口通讯......
  • 详解神经网络中反向传播和梯度下降
    摘要:反向传播指的是计算神经网络参数梯度的方法。本文分享自华为云社区《反向传播与梯度下降详解》,作者:嵌入式视觉。一,前向传播与反向传播1.1,神经网络训练过程神经网......
  • SpringCloud-全面详解(学习总结---从入门到深化)
    微服务架构进化论 单体应用阶段(夫妻摊位)在互联网发展的初期,用户数量少,一般网站的流量也很少,但硬件成本较高。因此,一般的企业会将所有的功能都集成在一起开发一个单体......
  • 多线程设计模式-全面详解(学习总结---从入门到深化)
    目录​​SingleThreadExecution设计模式​​​​机场过安检​​​​ 非线程安全​​​​ 问题分析​​​​首字母相同却未通过检查​​​​为何出现首字母不相同的情况......
  • HTMLReport使用2 | HTMLReport使用方法详解
    (2|HTMLReport的使用)注:以下实例来源于官网。1日志为测试报告中添加过程日志;多线程下,在报告中会分别记录每个线程的日志,同时会产生与测试报告同名的测试log文件。......
  • 【android 】android AlarmManager 详解
    在开发互联网应用时候,我们常常要使用心跳来保证客户端与服务器的连接。怎么完成心跳很关键,在说道客户端心跳功能时,如果使用Timer或者专门开起一个线程来做心跳的工作,会浪费......
  • 若依项目部署详解
    1.若依【前后端分离版】1.1.什么是若依若依就是别人写的开源项目,我们来做二次开放完成自己所需的业务,非常火的一个开源项目,能排在前面的开源项目!!!在于它的功能非常完整,选......