飞道的博客

dubbo解析-集群容错顶层抽象类AbstractClusterInvoker详解

364人阅读  评论(0)

本文基于dubbo 2.7.5版本代码

上一篇文章已经介绍了Cluster接口有10个实现类。每个Cluster实现类都会创建一个对应的Cluster Invoker对象。
MockClusterWrapper是包装类,ZoneAwareCluster在多个配置中心场景下使用,这两个类其他文章介绍。
其余的8个实现类及其对应的Cluster Invoker类如下:

Cluster Cluster Invoker 作用
FailoverCluster FailoverClusterInvoker
FailfastCluster FailfastClusterInvoker
FailsafeCluster FailsafeClusterInvoker
FailbackCluster FailbackClusterInvoker
ForkingCluster ForkingClusterInvoker
AvailableCluster AvailableClusterInvoker
MergeableCluster MergeableClusterInvoker
BroadcastCluster BroadcastClusterInvoker

Cluster Invoker类都继承AbstractClusterInvoker类,实现了抽象方法doInvoke。

AbstractClusterInvoker

AbstractClusterInvoker实现了接口Invoker。构造方法入参必须有Directory对象。
Directory对象叫做服务目录,持有全部可用的远程服务提供者列表,客户端使用远程服务提供者访问远程服务。远程服务提供者也实现了Invoker接口,如果远程服务以dubbo协议提供,那么客户端通过Invoker接口的实现类DubboInvoker访问。Directory后面的文章在做介绍。
AbstractClusterInvoker类中最关键的方法是:

public Result invoke(final Invocation invocation) throws RpcException

客户端访问远程服务时,首先调用AbstractClusterInvoker的invoke方法。如下图:

  1. 访问Directory的list方法在介绍Directory的时候做说明。
  2. 访问子类的doInvoke方法在介绍子类的时候,做介绍。
  3. select方法首先处理sticky参数。sticky默认为false,当设置为true时,表示在调用远程服务时,尽量使用之前使用过的远程服务提供者。AbstractClusterInvoker用字段stickyInvoker记录最后一次访问的服务提供者,下次再访问同一个服务的方法时,会使用stickyInvoker记录的服务提供者。如果sticky为false或者stickyInvoker不可用,那么会调用doSelect方法筛选服务。下面的代码做了删减,只保留了关键部分:
private Invoker<T> doSelect(LoadBalance loadbalance, Invocation invocation,
                                List<Invoker<T>> invokers, List<Invoker<T>> selected) throws RpcException {
        Invoker<T> invoker = loadbalance.select(invokers, getUrl(), invocation);
        if ((selected != null && selected.contains(invoker))
                || (!invoker.isAvailable() && getUrl() != null && availablecheck)) {
                Invoker<T> rInvoker = reselect(loadbalance, invocation, invokers, selected, availablecheck);
                if (rInvoker != null) {
                    invoker = rInvoker;
                } else {
                    int index = invokers.indexOf(invoker);
                    invoker = invokers.get((index + 1) % invokers.size());
                }
        }
        return invoker;
    }

doSelect首先通过Loadbalance从服务列表选择一个服务。当服务调用重试时,selected不为null,其记录了重试使用过的服务,如果负载均衡筛选出的服务不可用或者重试已经调用过,那么会调用reselect方法重新筛选。
reselect方法使用Loadbalance对服务列表做两次筛选,第一次是对不在selected列表的其他服务筛选,如果筛选不出来,那么进行第二次筛选,第二次筛选是从所有可用的服务中使用Loadbalance筛选。
select方法的总体流程如下:

select方法还涉及到参数cluster.availablecheck,默认为true。如果为true,上图菱形块中都会检查服务是否可用;如果设置false,菱形块中服务可用性不再检查,直接认为服务不可用。


转载:https://blog.csdn.net/weixin_38308374/article/details/105802044
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场