服务治理中间件 Dubbo 原理解析(集群容错)读书笔记
2018-08-24 15:01
232 查看
[code]第八章: 集群&容错 Dubbo 作为一个分布式的服务治理框架,提供了集群部署,路由,软负载均衡及 容错机制 下图描述了 dubbo 调用过程中的对于集群,负载等的调用关系。一: cluster 将 Directory 中的多个 Invoker 伪装成一个 Invoker, 对上层透明,包含集群的容错机制 Cluster 接口定义 @SPI(FailoverCluster.NAME) public interface Cluster { @Adaptive <T> Invoker<T> join(Directory<T> directory) throws RpcException; } Cluster 可以看做是工厂类, 将目录 directory 下的 invoker 合并成一个统 一的 Invoker,根据不同集群策略的 Cluster 创建不同的 Invoker 我们来看下默认的失败转移,当出现失败重试其他服务的策略, 这个 Cluster 实现很简单就是创建 FailoverCluseterInvoker 对象 public class FailoverCluster implements Cluster { public final static String NAME = "failover"; public <T> Invoker<T> join(Directory<T> directory) throws RpcException{ return new FailoverClusterInvoker<T>(directory); } } 下图展示了 dubbo 提供的所有集群方案 1) AvailableCluster: 获 取 可 用 的 调 用 。 遍 历 所 有 Invokers 判 断 Invoker.isAvalible,只要一个有为 true 直接调用返回,不管成不成功 2) BroadcastCluster: 广播调用。遍历所有 Invokers, 逐个调用每个调用 catch 住异常不影响其他 invoker 调用 3) FailbackCluster: 失败自动恢复, 对于 invoker 调用失败, 后台记录失败 请求,任务定时重发, 通常用于通知 4) FailfastCluster: 快速失败,只发起一次调用,失败立即保错,通常用于非 幂等性操作 5) FailoverCluster: 失败转移,当出现失败,重试其它服务器,通常用于读操 作,但重试会带来更长延迟 ( 1) 目录服务 directory.list(invocation) 列出方法的所有可调用服务 获取重试次数,默认重试两次 ( 2) 根据 LoadBalance 负载策略选择一个 Invoker ( 3) 执行 invoker.invoke(invocation)调用 ( 4) 调用成功返回调用失败小于重试次数,重新执行从 3)步骤开始执行 调用次数大于等于重试次数抛出调用失败异常 6) FailsafeCluster: 失败安全,出现异常时,直接忽略,通常用于写入审计日 志等操作。 7) ForkingCluster: 并行调用,只要一个成功即返回,通常用于实时性要求较 高的操作,但需要浪费更多服务资源。 8) MergeableCluster: 分组聚合, 按组合并返回结果,比如菜单服务,接口一 样,但有多种实现,用 group 区分,现在消费方需从每种 group 中调用一次 返回结果,合并结果返回,这样就可以实现聚合菜单项。 这个还蛮有意思,我们分析下是如何实现的 ( 1) 根据 MERGE_KEY 从 url 获取参数值 ( 2) 为空不需要 merge, 正常调用 ( 3) 按 group 分组调用,将返回接口保存到集合中 ( 4) 获取 MERGE_KEY 如果是默认的话,获取默认 merge策略主要根据返 回类型判断 ( 5) 如果不是,获取自定义的 merge 策略 ( 6) Merge 策略合并调用结果返回 9) MockClusterWrapper: 具备调用 mock 功能是其他 Cluster 包装 获取 url 的 MOCK_KEY 属性 ( 1) 不存在直接调用其他 cluster ( 2) 存在值 startsWith("force") 强制 mock调用 ( 3) 存在值不是 startsWith("force") 先正常调用,出现异常在mock调用 集群模式的配置 <dubbo:service cluster="failsafe" /> 服务提供方 <dubbo:reference cluster="failsafe" /> 服务消费方
[code]二: 目录服务 Directory 集群目录服务 Directory, 代表多个 Invoker, 可以看成 List<Invoker>, 它的值可能 是动态变化的比如注册中心推送变更。集群选择调用服务时通过目录服务找到所有服务 1.Directory 的接口定义 public interface Directory<T> extends Node { //服务类型 Class<T> getInterface(); //列出所有服务的可执行对象 List<Invoker<T>> list(Invocation invocation) throwsRpcException; } 2.Directory有两个具体实现 1.StaticDirectory: 静态目录服务 它的所有Invoker通过构造函数传入,服务消费方引用服务的时候,服务对多注册中心的引用, 将Invokers集合直接传入StaticDirectory构造器,再由Cluster伪装成一个InvokerStaticDirectory 的list方法直接返回所有invoker集合 2.RegistryDirectory: 注册目录服务 它的Invoker集合是从注册中心获取的, 它实现了NotifyListener接口实现了回调接口notify(List<Url>)。 比如消费方要调用某远程服务,会向注册中心订阅这个服务的所有服务提供 方,订阅时和服务提供方数据有变动时回调消费方的NotifyListener服务的 notify方法NotifyListener.notify(List<Url>) 回调接口传入所有服务的提供方的 url地址然后将urls转化为invokers, 也就是refer应用远程服务 到此时引用某个远程服务的RegistryDirectory中有对这个远程服务调用的所 有invokers。 3.registryDirectory.list(invocation)就是根据服务调用方法获取所有的远程服务引用 的invoker 执行对象
[code]三:路由 Router服务路由, 根据路由规则从多个Invoker中选出一个子集AbstractDirectory 是所有目录服务实现的上层抽象, 它在list列举出所有invokers后,会在通过 Router服务进行路由过滤。 Router接口定义 public interface Router extends Comparable<Router> { URL getUrl();<T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation)throws RpcException; } 1.ConditionRouter: 条件路由 我们这里简单分析下代码实现具体功能参考官方文档 条件表达式以 => 分割为whenRule和thenRule ConditionRouter创建,构造器初始 1) 从url根据RULE_KEY获取路由条件路由内容 2) rule.indexOf("=>") 分割路由内容 3) 分别调用parseRule(rule) 解析路由为whenRule和thenRules ConditionRouter执行route方法 1) 如果url不满足when条件即过来条件, 不过滤返回所有invokers 2) 遍历所有invokers判断是否满足then条件, 将满足条件的加入集合result 3) Result不为空,有满足条件的invokers返回 4) Result为空, 没有满足条件的invokers, 判断参数FORCE_KEY是否强制过 来,如果强制过滤返回空, 不是返回所有即不过滤 2.ScriptRouter: 脚本路由, 通过url的RULE_KEY参数获取脚本内容,然后通过java的脚本引擎执行脚本代 码, dubbo的测试用例都是通过javascript作为脚本但是理论上也支持groovy, jruby脚本,大家可以参考下测试用例ScriptRouterTest。ScriptRouter创建,构造器初始化 1) 从url获取脚本类型javascript, groovy等等 2) 从url根据RULE_KEY获取路由规则内容 3) 根据脚本类型获取java支持的脚本执行引擎 3.ScriptRouter执行route方法 1) 执行引擎创建参数绑定 2) 绑定执行的参数 3) 执行引擎编译路由规则得到执行函数CompiledScript 4) CompiledScript.eval(binds) 根据参数执行路由规则 4.Dubbo提供了ConditionRouterFactory, ScriptRouterFactory来创建对应的路由, 路由的规则从url的RULE_KEY参数来获取,路由规则可以通过监控中心或者治 理中心写入注册中心 Dubbo 也支持通过 FileRouterFactory 从文件读取路由规则,将读取的规则设置到 url 的 RULE_KEY 参数上, 文件的后缀代表了路由的类型,选择具体的路由工厂 ConditionRouterFactory, ScriptRouterFactory 来创建路由规则
[code]四:负载均衡 LoadBalance负载均衡, 负责从多个 Invokers中选出具体的一个Invoker用于本次 调用,调用过程中包含了负载均衡的算法,调用失败后需要重新选择 1.LoadBalance接口定义 @SPI(RandomLoadBalance.NAME) public interface LoadBalance { @Adaptive("loadbalance") <T> Invoker<T> select(List<Invoker<T>>invokers, URL url, Invocation invocation) throws RpcException; } 类注解@SPI说明可以基于Dubbo的扩展机制进行自定义的负责均衡算法实 现,默认是随机算法 方法注解@Adaptive说明能够生成设配方法 Select方法设配类通过url的参数选择具体的算法, 在从invokers集合 中根据具体的算法选择一个invoker 2.RandomLoadBalance: 随机访问策略,按权重设置随机概率,是默认策略 1) 获取所有invokers的个数 2) 遍历所有Invokers, 获取计算每个invokers的权重,并把权重累计加起来 每相邻的两个invoker比较他们的权重是否一样,有一个不一样说明权重 不均等 3) 总权重大于零且权重不均等的情况下 按总权重获取随机数offset = random.netx(totalWeight); 遍历invokers确定随机数offset落在哪个片段(invoker上)4) 权重相同或者总权重为0,根据 invokers个数均等选择 invokers.get(random.nextInt(length)) 3.RoundRobinLoadBalance: 轮询,按公约后的权重设置轮询比率 1) 获取轮询key 服务名+方法名 获取可供调用的invokers个数length 设置最大权重的默认值maxWeight=0 设置最小权重的默认值minWeight=Integer.MAX_VALUE 2) 遍历所有Inokers,比较出得出maxWeight和minWeight 3) 如果权重是不一样的根据key获取自增序列 自增序列加一与最大权重取模默认得到currentWeigth 遍历所有invokers筛选出大于currentWeight的invokers 设置可供调用的invokers的个数length 4) 自增序列加一并与length取模,从invokers获取invoker 4.LeastActiveLoadBalance: 最少活跃调用数, 相同的活跃的随机选择, 活跃数是指调用前后的计数差, 使慢的提供者收到更少的请求,因为越慢 的提供者前后的计数差越大。 活跃计数的功能消费者是在ActiveLimitFilter中设置的 最少活跃的选择过程如下: 1) 获取可调用invoker的总个数初始化最小活跃数,相同最小活跃的个数 相同最小活跃数的下标数组等等 2) 遍历所有invokers, 获取每个invoker的获取数active和权重 找出最小权重的invoker 如果有相同最小权重的inovkers, 将下标记录到数组leastIndexs[]数组中 累计所有的权重到totalWeight变量 3) 如果invokers的权重不相等且totalWeight大于0 按总权重随机offsetWeight = random.nextInt(totalWeight) 计算随机值在哪个片段上并返回invoker 4) 如果invokers的权重相等或者totalWeight等于0,均等随机 5.ConsistentHashLoadBalance:一致性hash, 相同参数的请求总是发到同一个提供者, 当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提 供者,不会引起剧烈变动。ConsistentashLoadBalance中对一致性哈希算法的实现, 还是比较通俗易懂的这里
阅读更多
相关文章推荐
- 15. Dubbo原理解析-集群&容错之目录服务Directory
- 16. Dubbo原理解析-集群&容错之router路由服务
- 14. Dubbo原理解析-集群&容错之Cluster
- 17. Dubbo原理解析-集群&容错之负载均衡
- 8. Dubbo原理解析-服务发布
- 19. Dubbo原理解析-通信层之暴露服务
- 微服务 Dubbo + Zookeeper 原理解析
- Dubbo服务集群,常见容错机制:failover ,failsafe,failfase ,failback,forking
- 20. Dubbo原理解析-通信层之引用服务
- dubbo源码解析(十) dubbo服务引用原理
- 分布式服务框架dubbo原理解析
- 9. Dubbo原理解析-服务引用
- HDFS集群繁忙时删除大量的文件导致NameNode服务不可用原理解析
- dubbo服务管理中间件底层原理
- 【DUBBO】Dubbo原理解析-服务发布
- 分布式服务框架dubbo原理解析 转
- Dubbo中集群Cluster,负载均衡,容错,路由解析
- 分布式服务框架dubbo原理解析
- 分布式服务框架dubbo原理解析
- 分布式服务框架dubbo原理解析(顶)