dubbo-remoting 模块提供了多种客户端和服务端通信功能。

  • 最底层部分即为 Remoting 层

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

Dubbo 整体架构设计图

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

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

dubbo-remoting-api 模块

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

  • buffer 包

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

  • exchange 包
    抽象了 Request 和 Response,并为其添加很多特性。这是整个远程调用核心部分。

  • transport 包
    抽象网络传输层,但只负责抽象单向消息传输,即请求消息由 Client 端发出,Server 端接收;响应消息由 Server 端发出,Client端接收。有很多网络库可以实现网络传输,如Netty, transport 包是在网络库上层的一层抽象。

传输层核心接口

“端点(Endpoint)”,可通过一个 ipport 唯一确定一个端点,两端点间会创建 TCP 连接,双向传输数据。Dubbo 将 Endpoint 之间的 TCP 连接抽象为(Channel)通道,将发起请求的 Endpoint 抽象为Client,接收请求的 Endpoint 抽象为Server。

Endpoint 接口

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

Channel

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

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

ChannelHandler

注册在 Channel 上的消息处理器,接口的定义

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

有一类特殊的 ChannelHandler 专门负责实现编解码功能,从而实现字节数据与有意义的消息之间的转换,或是消息之间的相互转换

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

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

接下来看Client 和 RemotingServer 两个接口,分别抽象了客户端和服务端,两者都继承了 Channel、Resetable 等接口,也就是说两者都具备了读写数据能力。

Client、RemotingServer

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

Client 和 Server 的主要区别:

  • Client 只能关联一个 Channel
  • Server 可接收多个 Client 发起的 Channel 连接,所以在 RemotingServer 接口中定义了查询 Channel 的相关方法

Transporter

  • Dubbo 在 Client 和 Server 之上又封装了一层Transporter 接口

@SPI 注解扩展接口,默认使用“netty”扩展名
@Adaptive 注解表示动态生成适配器类,会先后根据“server”“transporter”的值确定 RemotingServer 的扩展实现类,先后根据“client”“transporter”的值确定 Client 接口的扩展实现。

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

为什么要单独抽象出 Transporter层,不直接让上层使用 Netty?
正是利用了依赖反转原则(DIP),Netty、Mina、Grizzly 等 NIO 库对外接口和使用方式不同,若在上层直接依赖 Netty 或Grizzly,就依赖了具体的 NIO 库,而非依赖一个有传输能力的抽象,后续要切换实现的话,就需修改依赖和接入的相关代码。

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

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 { // ChannelHandlerDispatcherhandler = 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 集合的相关方法。

  • Endpoint 接口抽象了“端点”的概念,这是所有抽象接口的基础

  • 上层使用方会通过 Transporters 门面类获取到 Transporter 的具体扩展实现,然后通过 Transporter 拿到相应的 Client 和 RemotingServer 实现,就可以建立(或接收)Channel 与远端进行交互

  • 无论是 Client 还是 RemotingServer,都会使用 ChannelHandler 处理 Channel 中传输的数据,其中负责编解码的 ChannelHandler 被抽象出为 Codec2 接口。

  • Transporter 层整体结构图

参考

  • https://dubbo.apache.org/en-us/docs/dev/design.html

Dubbo Remoting模块详解相关推荐

  1. 分布式 | Dubbo 架构设计详解

    转载自   分布式 | Dubbo 架构设计详解 Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合).从服务 ...

  2. 【转】Dubbo架构设计详解

    本文转自:Dubbo架构设计详解,原作者是:时延军 Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合).从服 ...

  3. 【ES6】Module模块详解

    [ES6]Module模块详解 一.Module的由来 二.严格模式 三.export命令 四.import命令 查看更多ES6教学文章: 参考文献 引言:由于两个JS文件之间相互使用必须通过一个ht ...

  4. python常用内置模块-Python常用内置模块之xml模块(详解)

    xml即可扩展标记语言,它可以用来标记数据.定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言.从结构上,很像HTML超文本标记语言.但他们被设计的目的是不同的,超文本标记语言被设计用来显示 ...

  5. python之sys模块详解_(转)python之os,sys模块详解

    python之sys模块详解 原文:http://www.cnblogs.com/cherishry/p/5725184.html sys模块功能多,我们这里介绍一些比较实用的功能,相信你会喜欢的,和 ...

  6. Ansible基本使用及常用模块详解

    一.ansible基本使用 定义主机组 定义被管理节点列表的文件/etc/ansible/hosts,在定义被管理节点的时候,可以单独基于主机做定义,也可以将多个主机定义成一个主机组. 在上篇博文安装 ...

  7. Nginx源码研究之nginx限流模块详解

    这篇文章主要介绍了Nginx源码研究之nginx限流模块详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随小编过来看看吧 高并发系统有三把利器:缓存.降级和限流: 限流的目的是通过对并 ...

  8. python中json模块博客园_Python中的Json模块详解

    Python中的Json模块详解 Json(JavaScript Object Notation)它是一种轻量级的数据交换格式,具有数据格式简单,读写方便易懂等很多优点.许多主流的编程语言都在用它来进 ...

  9. python的sys模块有什么用_python sys模块详解

    Python sys 模块详解 1. 简介 "sys"即"system","系统"之意.该模块提供了一些接口,用于访问 Python 解释器 ...

  10. python time模块详解

    python time模块详解 转自:http://blog.csdn.net/kiki113/article/details/4033017 python 的内嵌time模板翻译及说明    一.简 ...

最新文章

  1. 有向图php,小蚂蚁学习数据结构(29)——图的存储表示
  2. poj 2516 最小费用最大流
  3. CDN简介及linux环境下搭建
  4. boost::bucket_sorter用法的测试程序
  5. Deeplab 在Qt Creator下编译报错undefined reference to Mat_xxx
  6. [AGC031E] Snuke the Phantom Thief(网络流)
  7. [渝粤教育] 三江学院 大学生创新基础课程 参考 资料
  8. 花了20分钟,给女朋友们写了一个web版群聊程序
  9. 数据结构(一)快速排序
  10. 兵马未动粮草先行,关于乐视模式的思考
  11. CentOS下安装JDK笔记
  12. 安徽师范大学数学计算机徐德琴,Snake模型在指纹图像分割中的应用
  13. html数据透视,Excel数据透视表使用过程中常见问题 如何在excel数据透视表中使用函数公式...
  14. HCIA-IoT 个人学习总结 Day2
  15. express静态文件
  16. [wordpress搬家]马来西亚 你好
  17. 云通讯这局棋,声网、容联云怎么破?
  18. ReactiveUI 入门
  19. C#泛型List 的定义、作用、用法
  20. windows文件服务器双机热备_实战教程:如何建立双机热备系统

热门文章

  1. Redis 如何使用 Bitmap
  2. IntPtr是什么,该怎么用?
  3. c语言小车路径规划算法,自动驾驶汽车四种常用的路径规划算法解析
  4. mysql实现用拼音搜索中文的数据库实现
  5. 图计算:社区发现算法
  6. Python爬虫之headers和data的获取
  7. qpsk 16qam matlab,谁能提供16qam和qpsk调制解调的ofdm程序
  8. 黑苹果固态硬盘_苹果SSD固态硬盘不完全详解
  9. jsp在校大学生助学贷款管理系统
  10. PDF转Word的时候需要输入密码怎么办?