前面提到过,重试是靠ClusterInvoker来保证的,不同的Cluster在调用失败的时候 做不同处理
比如默认的FailoverClusterInvoke的doInvoke方法里面:
int len = getUrl().getMethodParameter(invocation.getMethodName(), Constants.RETRIES_KEY, Constants.DEFAULT_RETRIES) + 1;
这个RETRIES_KEY就是重试次数,在后面的代码
for (int i = 0; i < len; i++)
这个就是用来在出现异常的时候,是继续调用,还是做其他处理,这个不同的ClusterInvoker实现是不同的。
比如FailoverClusterInvoker里面就是吞掉异常继续调用,除非次数用完,才真正抛出异常。
有个问题是经常调用方已经调用了,结果本地dubbo超时,继续又调用一次,可能导致consumer那边调用了两次,所以一般都是重试都是业务代码控制的。
为啥这样,还是因为FailoverClusterInvoker不区分超时Excpetion,虽然有不同错误码,但是如果是timeoutException,还是会继续重试
另外:
if (i > 0) {
checkWhetherDestroyed();
copyinvokers = list(invocation);
// check again
checkInvokers(copyinvokers, invocation);
}
这一句表示如果第一次调用失败,那么需要重新做一次list,也就是通过
List<Invoker<T>> invokers = directory.list(invocation);
return invokers;
让directory去注册中心重新拿一次,有可能这个时候provider已经发生变化