Dubbo 源码解析 —— 集群容错架构设计
前言
本来是想把整个dubbo源码解析一次性弄完,再做成一个系列来发布的,但是正巧最近有位好朋友要去杭州面试,就和我交流了一下.本着对dubbo源码略有心得的心态,在交流过程中也发表了个人的一些粗劣的拙见.但是非常不幸的是,交流过程中我这位朋友问到了几个问题,我却没能回答得上,让我感到十分惭愧.故而将原计划提前,并且定期整理,做到定期更新一篇dubbo源码解析.好让自己的知识盲点尽早暴露出来.本篇讲的就是dubbo的一个重要概念, 集群容错
.既然你已经在看源码解析了,那么我就假设你对dubbo的使用上有一定的经验,并且看过了dubbo的官网的对集群容错的简单介绍
之前有写过源码解析的一些拙见,例如别怕,手把手带你撕、拉、扯下SpringMVC的外衣, 别怕看源码,一张图搞定Mybatis的Mapper原理,但是经过一些思考还是有比较多的缺陷,这主要表现在太猴急,导致前戏不足,上来就直接进入源码,没有铺垫概念.大多数人看源码主要存在的问题是,层级结构深,导致进了两三个方法之后,根本不知道自己在哪,久而久之,对看源码产生了恐惧
所以本篇尝试改变之前的风格,总结起来就是先总体,后局部.也就是先把需要注意的概念先抛出来,把整体架构图先画出来.让读者拿着"地图"跟着我的脚步,并且每一步我都提醒,现在我们在哪,我们下一步要做什么,这样才不会迷失方向.
前期铺垫
这张是官网的对于集群容错的架构设计图,即使你有一定的使用经验,第一眼看到这个图可能还是有些懵逼.因为这个图是从设计的角度画出来的,而不是使用的角度.但是即使这个图你看不懂也不影响你对本文的阅读,但是你必须要记住三个关键词,因为这三个关键词接下来会贯穿全文,他们就是 Directory
, Router
, LoadBalance
再接下来给大家一张"地图","地图"上我已经标记了序号,再下面的源码分析中,我也会实时提醒我们所在的位置,以至于不会迷失方向.
环境准备
既然是集群,那么首先要启动两个 Provider
,我这里是一个虚拟机,一个本地的方式,因为环境准备不是本文重点,因此略过.本文所用到的源码是 2.5.4
版本,可以在 guihub
上找到.
正式发车
这次示例选用的源码用 dubbo-demo
的 dubbo-demo-consumer
,如果对dubbo原理有些简单的了解就知道,他给接口注入的不是接口的实现类,而是一个代理类,如下图
接着自然是到了代理类的invoke方法里,从图中我们也可以看出,他用的是 jdk的动态代理
下面要开始紧盯着地图了,他现在就要开始执行地图中的序号1,此时我们抵达 MockClusterInvoker
这个类
执行 invoke
就要开始进入到集群,也就是 Cluster
,现在第一个关键词 Directory
已经浮出水面了
现在到了 AbstractDirectory
,也就是序号3
这个 methodInvokerMap
也比较重要,后面的文章会讲一下这个,但是我们这部分代码就可以从出,他是要从 methodInvokerMap
中取出 invokers
如图所示
将invokers返回后(序号5),下面来到了第二个关键词, Router
,开始进入路由,现在我们到了序号6,此时到了 MockInvokersSelector
类,不要看类名和 Router
没有关系,其实他是 Router
接口的实现类,从官网的介绍图中我们也可以看到 Router
分为 Script
和 Condition
两种,翻译过来也就是 脚本路由
和 条件路由
这个后面再详细介绍,本篇主要介绍整体架构
源码的命名是很规范的,从 getNormalInvokers
就可以得知,他是要拿到能正常执行的 invokers
,并将其返回.也就是序号7
这个时候我们再次回到了 AbstractClusterInvoker
这个类,我们先不急着往下走,先适时做个总结.因为三个关键词,现在都已经出现了两个,那这个时候要回忆一下上面这些步骤,做一个总结.上面出现的这两个关键词,其实无非就是做两件事
-
在
Directory
中找出本次集群中的全部invokers
-
在
Router
中,将上一步的全部invokers
挑选出能正常执行的invokers
对应到"地图",也就是序号5和序号7.(再次提醒,一定要紧跟地图的序号,不然很容易迷失方向)
从上面步骤我们也知道,已经挑选出能正常执行的 invokers
了,但是假如2个做集群,但是这两个都是正常的,我到底要执行哪一个呢?带着这个问题,我们继续往下看
根据官网的描述
在集群调用失败时,Dubbo 提供了多种容错方案,缺省为 failover 重试。
所以这个时候是到了 FailoverClusterInvoker
类,但是如果你配置的是 FailfastCluster(快速失败)
, FailsafeCluster(失败安全)
, FailbackCluster(失败自动恢复)
, ForkingCluster(并行调用多个服务器,只要一个成功即返回)
, BroadcastCluster(广播调用所有提供者,逐个调用,任意一台报错则报错)
他也会到达相应的类
下面就要开始第三个关键词浮出水面,也就是 LoadBalance(负载均衡)
,此时的位置是序号11,仔细留心源码的注释,其实这里可以出一个面试题,比如
dubbo的负载均衡策略是怎么样的?
为什么这可以作为一道面试题,因为他可以区分三个层次的人.
- 如果是没有使用过,或者一直停留在使用层次的人,肯定不会留级到这个负载均衡策略.
- 根据官网介绍
在集群负载均衡时,Dubbo提供了多种均衡策略,缺省为random随机调用。
如果能回答出,缺省为随机调用的,说明还是有一定的使用经验,留意到官网的介绍 - 如果能回答出,缺省为随机调用,但是如果集群的数量为2,那么将退化成轮询.如果能回答到这个,那这个人就是有一定追求,不仅留心文档介绍,而且是看过源码,注意细节的人(比如本文作者肥朝 ^_^ )
根据前面我们知道,现在已经有两个备选的 invokers
,但是究竟哪一个能执行,这个需要 LoadBalance
来决定.这里涉及到了一定的算法,后面我也会有一篇文章加以介绍.剧透一下,这个在 2.5.4
的版本中,这个算法还是存在一些小的bug,此时我们的位置是序号13
到达终点站.我们回忆总结一下,文初提到的三个关键词,在这个集群容错的整体架构过程中,dubbo究竟做了什么.其实也就是三件事
-
在
Directory
中找出本次集群中的全部invokers
-
在
Router
中,将上一步的全部invokers
挑选出能正常执行的invokers
-
在
LoadBalance
中,将上一步的能正常的执行invokers
中,根据配置的负载均衡策略,挑选出需要执行的invoker
- Vijos P1114 FBI树【DFS模拟,二叉树入门】
- Vijos P1448 校门外的树【多解,线段树,树状数组,括号序列法+暴力优化】
- 撞库扫号防范
- 分享一个 HTTPS A+ 的 nginx 配置
- Vijos P1785 同学排序【模拟】
- Vijos P1784 数字统计【模拟】
- 网络安全黑暗森林法则:2015 ISC 深度回顾
- Codeforces 626G Raffles(贪心+线段树)
- window.opener.location 安全风险讨论
- Vijos P1497 立体图【模拟】
- Vijos P1127 级数求和【模拟】
- 新型漏洞:利用浏览器Cookie绕过HTTPS并窃取私人信息
- Vijos P1113 不高兴的津津【模拟】
- Linux下MySQL的彻底卸载和安装配置字符集
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- ROS自平衡车案例学习(机器人操作系统+现代控制理论融合)
- Git 不能提交空目录?我也是醉了!
- 相关矩阵、特征、预测、股市!(附代码)
- CentOS7下编译安装libmodbus库
- 你还以为使用 StringBuffer 就万事大吉了?
- Windows10中VS2017环境下使用libmodbus库Modbus TCP读取设备的数据
- 记一次生产服务器进程突然消失问题排查!
- 0812-7.1.3-如何使用Ranger给HBase授权
- Redis集群方案对比:Codis、Twemproxy、Redis Cluster
- 这就是你日日夜夜想要的docker!!!---------Docker镜像制作与私有仓库建立
- 排障集锦:九九八十一难之第十八难!-----System has not been booted with systemd as init system (PID 1). Can‘t operat
- 深入了解 Flex 属性
- 如何设计一个安全的短信接口?
- ERROR Shell:396 - Failed to locate the winutils binary in the hadoop binary path java.io.IOE...
- Windows 安装配置 PySpark 开发环境(详细步骤+原理分析)