博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Dubbo源码分析-Remoting层
阅读量:6689 次
发布时间:2019-06-25

本文共 4200 字,大约阅读时间需要 14 分钟。

hot3.png

Dubbo Remoting 模块是dubbo底层通信模块的实现。实现对请求/应答的各种逻辑处理,包括同步,异步,心跳等逻辑,最底层的通信借助netty或者mina实现,还有通过jetty servlet暴漏http服务的实现方式。

Remoting Api

公共基础接口类

  • Endpoint

Endpoint 字面意思是端点,端点接口的基本操作有获取端点对应的URL,LocalAddress,及发送关闭Channel的操作;

  • Channel

Channel接口继承Endpoint ,多了对Attribute的操作接口(get,set,remove)及获取连接状态接口,多了获取远端的操作getRemoteAddress方法;

  • ChannelHandler

ChannelHandler 主要包含对Channel的一些处理:

connected(Channel channel);
disconnected(Channel channel);
sent(Channel channel, Object message);
received(Channel channel, Object message);

  • Client

Client继承了Endpoint, Channel, Resetable,并添加reconnect接口

  • Server

Server除了继承Endpoint,还多了下面两个接口:

Collection<Channel> getChannels() 获取所有的Channel;
Channel getChannel(InetSocketAddress remoteAddress) 根据地址获取特定Channel;

  • Codec

encode,decode 编码解码消息

  • Transporter

Server bind(URL url, ChannelHandler handler) 监听服务端

Client connect(URL url, ChannelHandler handler) 连接到服务端 Transporter 实现类根据采用的底层通信框架的不同,具体封装不同的实现比如netty如图:
输入图片说明

输入图片说明

总结一下这几个基础接口的关系,从Endpoint,Channel,Client,Server的继承关系可以看出,Endpoint作为基础接口包含一些获取端点地址,获取channelHandler,发送消息的接口;
Channel继承Endpoint,Channel可以理解成现实的生活中的水管,它有端点的属性,同时它又有本身的属性;
Client本身是个端点,同时它又可以借助Channel对Server进行连接,它只能对属于它的那个Channel进行操作;
Server本身也是个端点,但它没有继承Channel,因为它是要对多个Channel进行有选择的操作,所以它才有上门列举的那两个操作; Transporter接口明显功能是发起客户端连接或者服务端监听的作用,Transporters的作用主要是通过dubbo采用的SPI思想去根据配置加载Transporter具体实现类,去完成相应的动作;
这里涉及的Client Server Channel都是上层通用对象的抽象,预定义通用属性方法,底层可以灵活的借用不同的框架去实现。大家不要把这些概念和netty mina里的概念混淆。

Buffer包

该包下的类主要是对字节码的操作的封装,ChannelBuffer定义了相应的操作接口,它的实现有Heap实现,和堆外直接内存两张实现;ChannelBuffers实现了对ChannelBuffer操作工具;大概类图如下:

输入图片说明

Transport包

输入图片说明

这里主要是对Client接口的部分实现,AbstractClient实现了Client大部分功能,仅把具体的通信操作留给所依赖的底层通信框架来实现。它实现了连接时锁控制逻辑,重试机制,及加载所要采用的线程池等逻辑。 AbstractServer 里面的逻辑想对简单,仅仅是对一些属性做了些准备,比如从url中解析所要监听的地址,获取线程池,还实现了一个对所有客户端发送消息的send方法。

输入图片说明

上面类图主要展示ChannelHandler的相关实现,ChannelHandler主要是触发Channel进行 CONNECTED,DISCONNECTED,SENT,RECEIVED,CAUGHT这个五个操作,其中WrappedChannelHandler对ChannelHandler做了包装,采用了装饰者模式,直接调用构造函数传入的handler来触发相关操作。这里的Handler设计巧妙,handler里嵌handler,每个handler只需做自己的特殊处理然后交给下一个handler即可,形成了一个处理链,实现功能的分层实现。这里会产生一个疑问,大家这些ChannelHandler都在做自己的业务逻辑处理然后调用handler.xxx(channel),好像谁也没有去触发channel上的动作,这个是在client去做的,其实client本身实现了ChannelHandler接口,比如NettyClient。 上图中的AllChannelHandler ,ExecutionChannelHandler,MessageOnlyChannelHandler,ConnectionOrderedChannelHandler 都是起到分发执行handler动作的类,他们都放在dispatcher包下面,只不过有的是在线程池里去异步执行的具体的handler对channel的操作,有的是直接在本线程中直接执行。

Exchange包

输入图片说明

Exchange这个包下的类主要是提供了可发起远程请求的ExchangeClient,和监听服务端的ExchangeServer。其具体实现分别是HeaderExchangeClient和HeaderExchangeServer。 Exchangers 调用 HeaderExchanger去实现客户端connect,服务端bind动作,分别生成HeaderExchangeClient与HeaderExchangeServer。 输入图片说明

这里Transporters会根据配置的具体Transporter实现类(NettyTransporter,MinaTransporter)来实例化具体的Client,或Server。

输入图片说明

Exchange包层主要是ExchangeClient ExchangerServer ,他们在Transport层上加入了心跳检测,也加入了异步处理逻辑的实现ResponseFuture。其中ResponseFuture 的实现类DefaultFuture,主要是借助ReentrantLock和Condition实现,大家可以看下源码。

Telnet包

输入图片说明

该包下的类主要是实现了一些handler,通过telnet命令行查询状态,log等信息。

Remoting Netty

上面的逻辑把remoting层的功能大概实现了,唯独把依赖底层通信框架的部分抽象给具体的框架实现。Dubbo底层实现有Mina,Netty,Grizzly,还有借助jetty把服务暴漏成http的方式。这里我们只简单的介绍下借助Netty的实现。 这里分别介绍下NettyChannel, NettyClient, NettyServer, NettyHandler, NettyTransporter。

NettyChannel除了继承dubbo本身定义的Channel接口逻辑,这里它把Netty中的Channel概念作为构造参数传入,因为所有的交互最终还是依赖netty中的channel去做。

NettyHandler这里是实现扩展了SimpleChannelHandler,同时把dubbo中定义的handler作为构造参数传入,当触发了netty中的读 写 连接断开等事件时,就会执行各种handler里定义的逻辑。

NettyClient 这里的逻辑比较简单,就是实现AbstractClient中留下的各种doXXX抽象方法,发起远程连接。

NettyServer 通过Netty bootstrap开启服务端监听。

这里把dubbo remoting层涉及到的概念和逻辑基本介绍了。那这里以Netty Remote为例总结一些Client和Server的基本流程。

Client:通过HeaderExchanger调用connect方法 new HeaderExchangeClient(Transporters.connect(url, new DecodeHandler(new HeaderExchangeHandler(handler)))); —》NettyTransporter 调用connect方法 new NettyClient(url, listener)。这样一个连接就诞生了。

Server: 通过HeaderExchanger调用bind方法 new HeaderExchangeServer(Transporters.bind(url, new DecodeHandler(new HeaderExchangeHandler(handler)))); —》NettyTransporter 调用bind方法 new NettyServer(url, listener)。这样监听诞生。

框架代码设计小技巧

1 引入使用频率较高第三方类库时,如果类库比较小如fastjson, asm类库为了防止jar冲突,可以直接把源码copy到项目中;

2 在设计抽象类时,比如dubbo的AbstractClient,比如方法的一些公共部分抽离出来,不确定的部分包到抽象方法里,留给子类实现;方法的命名很有技巧 比如 方法open里已知的逻辑我们写直接在抽象类里写,要留给子类的逻辑我们起个抽象方法doOpen。

输入图片说明

下节介绍dubbo rpc层的逻辑。

转载于:https://my.oschina.net/robinyao/blog/804182

你可能感兴趣的文章
Java函数式编程和lambda表达式
查看>>
Android:Activity(八):Fragment的生命周期
查看>>
【视频】 安卓***课程收集整理
查看>>
按某一列里面同一类横向显示数据总数
查看>>
rsyslog 客户端监控
查看>>
用maven快速搭建spring mvc的web项目(配置到jackson 和 任务调度)
查看>>
Kotlin
查看>>
windows平台升级ORACLE11.2.0.1到11.2.0.4
查看>>
nginx日志分析
查看>>
eureka多注册中心
查看>>
spring 数据源动态切换 与dubbo服务
查看>>
linux系统批量修改root用户密码
查看>>
我的shell×××作
查看>>
天猫超市低调运营 马云尝试自营B2C模式
查看>>
选择Palo Alto 防火墙十大理由
查看>>
Linux下解压,压缩JAR包的简单方法
查看>>
领先盘点2013年办公家具风格潮流趋势
查看>>
分布式事务:两阶段提交与三阶段提交
查看>>
linux deepin升级内核后,vmware需要gcc编译器
查看>>
针对IE6\7\8\9\10浏览器的CSS hack大全详解
查看>>