dubbo原理图
从图中我们可以看到,dubbo整体架构分为4个部分即服务提供者、注册中心、服务消费者、监视者。
- 服务容器负责启动,加载,运行服务提供者。
- 服务提供者在启动时,向注册中心注册自己提供的服务。
- 服务消费者在启动时,向注册中心订阅自己所需的服务。
- 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
- 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
- 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
一、Provider如何暴露服务
Dubbo会在Spring实例化完成bean之后,在刷新容器最后一步发布ContextRefreshEvent事件的时候,通知实现了ApplicationListener的ServiceBean类进行回调onApplicationEvent 事件方法,调用ServiceBean的export方法,实现服务的导出。
export的步骤:
- 首先会检查各种配置信息,保证在开始暴露服务之前所有东西都是准备好的。
- 根据配置的协议和注册中心的url 向注册中心进行注册(dubbo支持将一个服务发布为多种协议)
- 注册的时候也要进行属性检查
- 如果配置的不是remote,则作本地导出
- 如果不是Local,则暴露为远程服务。
- 服务代理类 Invoker
- 包装Invoker为Exporter进行返回
底层通过netty创建服务,根据URL中相应的Key来调用对应的invoker
主要组件
Invoker 这里的Invoker是Provider的一个可调用Service的抽象,Invoker封装了Provider地址及Service接口信息。
Exporter 负责Invoker的生命周期,包含一个Invoker对象
Excahnger 负责数据交换和网络通信
二、Consumer如何引入服务
Dubbo 服务引用的时机有两个,第一个是在 Spring 容器调用 ReferenceBean 的 afterPropertiesSet 方法时引用服务(初始化bean的时候),第二个是在 ReferenceBean 对应的服务被注入到其他类中时引用。这两个引用服务的时机区别在于,第一个是饿汉式的,第二个是懒汉式的。默认情况下,Dubbo 使用懒汉式引用服务。
引入服务的过程:
- 对URL配置进行检查和处理,以保证配置到正确性。
- 检查配置是本地调用还是远程调用
- 创建Invoker。在服务提供方,Invoker 用于调用服务提供类。在服务消费方,Invoker 用于执行远程调用(构建Netty客户端)。
- 创建代理
三、Dubbo集群容错
集群容错源码包含四个部分,分别是服务目录 Directory、服务路由 Router、集群 Cluster 和负载均衡 LoadBalance。这几个部分的源码逻辑相对比较独立,我们将会分四篇文章进行分析。
当我们的系统中用到Dubbo的集群环境,因为各种原因在集群调用失败时,Dubbo提供了多种容错方案,缺省为failover(重试)。
- Directory代表多个Invoker,可以把它看成List<Invoker>,它的值可能是动态变化的,比如注册中心推送变更。
- 服务目录在刷新 Invoker 列表的过程中,会通过 Router 进行服务路由,筛选出符合路由规则的服务提供者。
- Cluster将Directory中的多个Invoker(这几个Invoker提供相同的服务)伪装成一个Invoker,对上层透明,伪装过程包含了容错逻辑,调用失败后,重试另一个。
Dubbo 主要提供了这样几种容错方式:
- Failover Cluster - 失败自动切换
- Failfast Cluster - 快速失败
FailfastClusterInvoker 只会进行一次调用,失败后立即抛出异常。适用于幂等操作,比如新增记录- Failsafe Cluster - 失败安全
FailsafeClusterInvoker 是一种失败安全的 Cluster Invoker。所谓的失败安全是指,当调用过程中出现异常时,FailsafeClusterInvoker 仅会打印异常,而不会抛出异常。- Failback Cluster - 失败自动恢复
FailbackClusterInvoker 会在调用失败后,返回一个空结果给服务提供者。并通过定时任务对失败的调用进行重传,适合执行消息通知等操作。- Forking Cluster - 并行调用多个服务提供者
ForkingClusterInvoker 会在运行时通过线程池创建多个线程,并发调用多个服务提供者。只要有一个服务提供者成功返回了结果,doInvoke 方法就会立即结束运行
- LoadBalance负责从Cluster中选出具体的一个用于本次调用,选的过程包含了负载均衡算法,调用失败后,需要重选。
Dubbo 提供了4种负载均衡实现,分别是基于权重随机算法的 RandomLoadBalance、基于最少活跃调用数算法的 LeastActiveLoadBalance、基于 hash 一致性的 ConsistentHashLoadBalance,以及基于加权轮询算法的 RoundRobinLoadBalance。
对于一致性hash
避免数据倾斜问题
这里相同颜色的节点均属于同一个服务提供者,比如 Invoker1-1,Invoker1-2,……, Invoker1-160。这样做的目的是通过引入虚拟节点,让 Invoker 在圆环上分散开来,避免数据倾斜问题。所谓数据倾斜是指,由于节点不够分散,导致大量请求落到了同一个节点上,而其他节点只会接收到了少量请求的情况。比如:
四、调用规则
cluster Invoker的调用过程,首先Router根据路由规则从Directory中选出Invoker子集作为Cluster,然后利用LoadBalance实现负载均很选出具体的Invoker。
网友评论