Dubbo是一个精耕服务治理领域的框架,秉承了阿里一贯的大而全风格,和Eureka相比复杂度有不小的提高,这一节我们选了Registry和Remoting两个核心模块,从功能层面做个简单的了解(后面的章节会深入介绍底层原理)
Registry是Dubbo中负责服务注册的模块,也就是我们熟悉的注册中心,目前Dubbo支持五种不同的注册中心,其中登场率最高的就是Zookeeper了。
Zookeeper是Apache Hadoop的子项目,它底层是一个树形的目录结构,同时支特基于发布订阅模型的变更推送,这个特性特别适合应用在注册中心服务上。Zookeeper在各个大厂都有广泛应用,其稳定性和性能已经在业界得到了充分证明。大家如果想进一步了解Zookeeper可以逛逛官方开源文档: http://zookeeper.apache.org
关于Registry的细节部分将在稍后一小节深入讲解,在这之前我们先了解下Dubbo在服务注册功能上的主要特点:
注册中心只承担服务治理相关的功能(注册、发现、心跳和下线等),它不承担消息的转发(这一点和Eureka一样),因此不用承担访问压力。和Eureka相比,Dubbo在服务治理领域走的完全是不同的风格路线,我们从各个功能上先来做一个了解
Eureka的注册中心在服务治理领域采用的是一种“佛系”的连接策略,比如服务发现和心跳检测,都是等待服务节点自己上报状态。而Dubbo相比较之下就是“事必躬亲”的管理策略,Dubbo的注册中心,服务提供者和服务消费者三者之间均为长连接,注册中心严密监测节点的状态变化。
Dubbo的注册中心基于长连接感知服务提供者的状态,假如服务提供者宕机,注册中心将立即推送事件通知消费者。但是注册中心自身宕机并不会影响已经上线运行的服务提供者和消费者。
当服务提供者出现异常情况的时候(比如电源又被挖掘机铲断了)注册中心利用长连接可以侦听到服务的不可用状态,进而在服务列表中删除服务提供者。
我们以Zookeeper注册中心为例,Dubbo的服务 剔除原理实际上是利用Zookeeper的临时节点和会话保持的功能。ZK中的数据是和一一个会话绑定的,一旦会话异常ZK就会清除这个会话创建的临时节点和所有订阅该会话的Watcher。
我们结合Dubbo的长连接和服务剔除机制,讲一讲ZK中的会话(Session)是怎么一回事儿。在ZK中当一个长连接建立起来后,会生成一个SessionID,这是一个全局唯-的标识符。在会话期间内ZK通过心跳感应连接状态,如果在会话过期时间内没有心跳发送过来或者因为网络原因导致会话断掉,那么这个时候客户端就会重新选择新的ZK节点进行连接。因此,当会话过期时,Dubbo的服 务提供者和消费者能自动恢复注册数据,重新订阅请求。
Eureka则不同,Eureka后 台有-一个服务自保的机制,也就是说短期的网络波动导致大比例节点无法连接到注册中心的时候,Eureka会开启自保模式,在这个模式下服务剔除功能将被禁用。
Dubbo同样也有心跳检测,它的目的是检测服务提供者和服务消费者之间的连接是否还处于可用状态。如果在默认60s没有消息进来的时候,会尝试发送一个心跳Request,如果连着180秒既没有消息也没心跳,那么则会关闭Channel,对于Consumer来说则需要重新连接一个新的Provider。
服务提供者向注册中心注册其提供的服务,并汇报调用时间到监控中心。服务消费者向注册中心获取服务提供者地址列表,并根据负载算法直接调用提供者,同时汇报调用时间到监控中心。
监控中心是一个可选组件,可以根据自身项目需要决定是否接入。监控中心和各个节点之间并不是长连接,同时监控中心的宕机并不会影响任何服务调用,只不过可能会丢失一部分的监控数据而已。
Remoting模块主要负责远程调用,核心部分是Dubbo的协议栈实现,处于整个调用链路中相对底层的部分。在这里我们简单的看下Remoting框架的接口结构。
AbstractPeer实现了上面提到的两个顶层接口,它是一-种代理模式的组合结构,通过构造器接收- -个ChannelHandler对象,然后把方法实现的具体逻辑委托给ChannelHandler对象来实现,随手拿一个接收消息的代码来举例:
@Override
public void received(Channel ch, 0bject msg) throws Rem0tingException {
if (closed) {
return;
}
handler.received(ch, msg);
}
AbstractChannel添加了send方法(发送消息到远程服务)的缺省验证逻辑,作为NettyChannel等 具体底层实现类的统一父类
Client作为服务调用的发起方(消费者)的顶层接口,继承了Endpoint和Channel接口的同时,还定义了reconnect方法,用来重新连接到Server。Dubbo中的底层服务调用实现类(比如NettyClient和MinaClient)都继承自Client,但是Client只是个发起服务调用的壳,底层的调用逻辑都被封装在Channel对象里(AbstractChannel的子类,比如NettyChannel)
Server作为服务提供方的顶层接口,继承自Endpoint和Resetable的同时,又定义了一系列服务端的接口方法,比如获取Channel列表或某个指定Channel
本文已收录至我的个人网站:程序员波特,主要记录Java相关技术系列教程,共享电子书、Java学习路线、视频教程、简历模板和面试题等学习资源,让想要学习的你,不再迷茫。