Dubbo Cluster 集群的作用是什么?

  • 生产环境下, 常常会用多个服务器跑同一个应用, 目的是为了避免单点故障;
  • 此时, 对于服务消费者来说, 同一环境下就出现了多个服务提供者, 会带来一些问题:
    • 对于一次请求, 作为消费者到底应该调用哪个提供者?
    • 服务调用失败的时候, 消费者应该怎么做? 是重试? 是抛出异常? 或者仅仅是打印出异常?
  • 为了处理上述问题, Dubbo定义了集群接口 Cluster 以及 Cluster Invoker;
  • 集群 Cluster 的用途是将多个服务提供者合并为一个 Cluster Invoker,并将这个 Invoker 暴露给服务消费者。
  • 这样的好处就是对服务消费者来说,只需通过这个 Cluster Invoker 进行远程调用即可,至于具体调用哪个服务提供者,以及调用失败后如何处理等问题,现在都交给集群模块去处理。
  • 集群模块是服务提供者和服务消费者的中间层,为服务消费者屏蔽了服务提供者的情况,这样服务消费者就可以专心处理远程调用相关事宜。比如发请求,接受服务提供者返回的数据等。这就是 Dubbo Cluster 集群的作用。

    Dubbo Cluster 的 10 个实现类你能说出来几个,其中哪几个是集群容错的方法实现?

    集群策略 - 图1

  • 需要注意的是,十种实现方法其中只有 failover、failfast、failsafe、failback、forking、broadcast 这 6 种才属于集群容错的范畴。另外的实现均有其他的应用场景。

  • FailoverCluster:失败自动切换,在调用失败时,失败自动切换,当出现失败,重试其它服务器。通常用于读操作,但重试会带来更长延迟。可通过 retries=”2” 来设置重试次数 (不含第一次)。
  • FailfastCluster: 快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。
  • FailsafeCluster: 失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。
  • FailbackCluster: 失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
  • ForkingCluster: 并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks=”2” 来设置最大并行数。
  • BroadcastCluster: 广播调用所有提供者,逐个调用,任意一台报错则报错。通常用于通知所有提供者更新缓存或日志等本地资源信息。
  • AvailableCluster: 获取可用的服务方。遍历所有 Invokers 通过 invoker.isAvalible 判断服务端是否活着,只要一个有为 true,直接调用返回,不管成不成功。
  • MergeableCluster: 分组聚合,将集群中的调用结果聚合起来,然后再返回结果。比如菜单服务,接口一样,但有多种实现,用 group 区分,现在消费方需从每种 group 中调用一次返回结果,合并结果返回,这样就可以实现聚合菜单项。
  • MockClusterWrapper: 本地伪装,通常用于服务降级,比如某验权服务,当服务提供方全部挂掉后,客户端不抛出异常,而是通过 Mock 数据返回授权失败。
  • ZoneAwareCluster: 双注册中心环境下, 对应的消费端, 先在注册中心间选择, 再到选定的注册中心选址, 目前的设计如下:

集群策略 - 图2

  • 指定优先级:来自 preferred=”true” 注册中心的地址将被优先选择,只有该中心无可用地址时才 Fallback 到其他注册中心
  • 同 zone 优先:选址时会和流量中的 zone key 做匹配,流量会优先派发到相同 zone 的地址
  • 权重轮询:来自北京和上海集群的地址,将以 10:1 的比例来分配流量
  • 默认方法:选择第一个可用的即可;

集群策略 - 图3
集群策略 - 图4

默认的集群实现类是什么呢?

  • FailoverClusterInvoker

    Failover Cluster 调用失败之后,会自动进行几次重试呢?

  • 默认重试次数是 2 次

集群策略 - 图5
集群策略 - 图6

  • doInvoke 方法

集群策略 - 图7

  • 首先是获取重试次数,然后根据重试次数进行循环调用,在循环体内,如果失败,则进行重试。
  • 在循环体内,首先是调用父类 AbstractClusterInvoker 的 select 方法,通过负载均衡组件选择一个 Invoker ,然后再通过这个 Invoker 的 invoke 方法进行远程调用。
  • 如果失败了,记录下异常,并进行重试。
  • 注意一个细节:在进行重试前,重新获取最新的 invoker 集合,这样做的好处是,如果在重试的过程中某个服务挂了,可以通过调用 list 方法可以保证 copyInvokers 是最新的可用的 invoker 列表。

    什么是 Dubbo 的粘滞连接?

  • 官方解释:

集群策略 - 图8

粘滞连接在 Cluster 中是怎么应用的?

  • AbstractClusterInvoker select 源码

集群策略 - 图9
集群策略 - 图10

  • 粘滞连接和可用性检测的默认配置: 默认情况下粘滞连接是关闭状态。当粘滞连接开启时,默认会进行可用性检查。

    Cluster 选择出一个可用的 Invoker 最多要进行几次选择?

  • 最多进行三次选择;

  • AbstractClusterInvoker doSelect 源码解析
    • ①:通过负载均衡组件选择 Invoker。
    • ②:如果选出来的 Invoker 不稳定,或不可用,此时需要调用 reselect 方法进行重选。
    • ③:reselect 选出来的 Invoker 为空,此时定位 invoker 在 invokers 列表中的位置 index,然后获取 index+1 处的 invoker。

集群策略 - 图11

  • AbstractClusterInvoker reselect 源码解析

集群策略 - 图12
集群策略 - 图13

  • 第一:查找可用的 invoker,并将其添加到 reselectInvokers 集合中。这个 reselectInvokers 集合你可以理解为里面放的是所有的可用的 invoker 的集合与 selected 集合的差集。
  • 第二:如果经过筛选后,reselectInvokers 不为空,则通过负载均衡组件再次进行选择并返回。
  • 第三:如果经过筛选后,reselectInvokers 为空,则再从 selected 集合 (已经被调用过的集合) 中选出所有可用的 invoker,放到 reselectInvokers 中,再次通过负载均衡组件进行选择并返回。
  • 第四:如果进过上面的步骤后,没有选择出合适的 invoker,reselectInvokers 还是为空,说明所有的 invoker 都不可用了,返回为 null。

    请问几次选择分别是什么?

  • ①:通过负载均衡组件选择 Invoker。

  • ②:如果选出来的 Invoker 不稳定,或不可用,此时需要调用 reselect 方法进行重选。
  • ③:reselect 选出来的 Invoker 为空,此时定位 invoker 在 invokers 列表中的位置 index,然后获取 index+1 处的 invoker。