上一篇文章已经介绍了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方法。如下图:
- 访问Directory的list方法在介绍Directory的时候做说明。
- 访问子类的doInvoke方法在介绍子类的时候,做介绍。
- 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,菱形块中服务可用性不再检查,直接认为服务不可用。