dubbo-remoting 模块提供多种客户端和服务端通信功能。最底层部分即为 Remoting 层:
包括 Exchange、Transport和Serialize 三层。本文主要描述 Exchange 和 Transport 两层。
Dubbo直接集成已有的第三方网络库,如Netty、Mina、Grizzly 等 NIO 框架:
dubbo-remoting-zookeeper使用 Apache Curator 实现与 zk 的交互。
是其他 dubbo-remoting-* 模块的顶层抽象,其他 dubbo-remoting 子模块都是依赖第三方 NIO 库,来实现 dubbo-remoting-api 模块。
定义Buffer相关接口、抽象类及实现类。在各 NIO 框架中都有自己的缓冲区实现。但这里的 buffer 包在更高层面,抽象各个 NIO 框架的缓冲区,同时也提供一些基础实现。
抽象 Request、Response,并为其添加很多特性。整个远程调用的核心部分。
抽象网络传输层,但只负责抽象单向消息传输,即:
很多网络库可实现网络传输,如Netty,transport包是在网络库上层的一层抽象。
“端点(Endpoint)”:一个 ip 和 port 唯一确定,两端点间会创建 TCP 连接,双向传输数据。
Dubbo 将 Endpoint 之间的 TCP 连接抽象为(Channel)通道:
对 Endpoint 双方连接的抽象,就像传输管道。消息发送端往 Channel 写入消息,接收端从 Channel 读取消息。
继承 Endpoint 接口,也具备开关状态以及发送数据能力。可在 Channel 上附加 KV 属性:
注册在 Channel 上的消息处理器
@SPI 注解表明该接口是一个扩展点。
有一类特殊的 ChannelHandler 专门负责实现编解码功能,实现:
该接口也是个扩展接口,encode()、decode() 被 @Adaptive 注解修饰,也就会生成适配器类,其中会根据 URL 中的 codec 值确定具体的扩展实现类。
DecodeResult 枚举是在处理 TCP 传输时粘包和拆包使用的,如当前能读取到的数据不足以构成一个消息时,就使用 NEED_MORE_INPUT 。
分别抽象客户端、服务端,都继承 Channel、Resetable 等接口,即都具备读写数据的能力。
都继承了 Endpoint,只是在语义上区分请求和响应职责,都具备发送数据能力。
Dubbo 在 Client、Server 之上又封装一层Transporter 接口:
@SPI 注解扩展接口,默认使用“netty”扩展名。
@Adaptive 注解表示动态生成适配器类:
几乎对每个支持的 NIO 库,都有接口实现:
利用依赖倒置原则,Netty、Mina、Grizzly 等 NIO 库对外接口和使用方式不同,若在上层直接依赖 Netty 或Grizzly,就依赖具体 NIO 库,而非依赖一个有传输能力的抽象,后续要切换实现,就需修改依赖和接入的相关代码。
而有了 Transporter 层,就可通过 Dubbo SPI,修改使用的具体 Transporter 扩展实现,切换到不同 Client 和 RemotingServer 实现,切换底层 NIO 库,而无须修改代码。当有更先进的 NIO 库出现,也只需开发相应的 dubbo-remoting-* 实现模块提供 Transporter、Client、RemotingServer 等核心接口的实现,即可接入,完全符合开放封闭原则。
不是一个接口,而是门面类,封装:
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 集合的相关方法。
参考: https://dubbo.apache.org/en-us/docs/dev/design.html
本文转载自微信公众号「JavaEdge」,可以通过以下二维码关注。转载本文请联系JavaEdge公众号。
网页题目:Dubbo的Remoting模块解析
地址分享:http://www.mswzjz.cn/qtweb/news13/427163.html
攀枝花网站建设、攀枝花网站运维推广公司-贝锐智能,是专注品牌与效果的网络营销公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 贝锐智能