Dubbo服务消费者Consumer调用流程(七)
在上一篇中提到了RegisteryProtocol#doRefer里面的invoker
为 MockClusterInvoker。
我们在ExtensionLoader一节中,漏讲了一个细节,那就是获取自适应扩展类的时候,采用字节码生成技术的时候,生成的$Adaptive类中获取扩展类是通过ExtensionLoader#getExtension来实现的,
里面有个createExtension方法,其中代码段:
//将该instance依次使用包装类包裹 if (CollectionUtils.isNotEmpty(wrapperClasses)) { for (Class<?> wrapperClass : wrapperClasses) { instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance)); } }
这个意思就是说根据SPI文件中定义的包装类,一次包装instance。我们以Cluster举例:
SPI定义:
mock=org.apache.dubbo.rpc.cluster.support.wrapper.MockClusterWrapper failover=org.apache.dubbo.rpc.cluster.support.FailoverCluster failfast=org.apache.dubbo.rpc.cluster.support.FailfastCluster failsafe=org.apache.dubbo.rpc.cluster.support.FailsafeCluster failback=org.apache.dubbo.rpc.cluster.support.FailbackCluster forking=org.apache.dubbo.rpc.cluster.support.ForkingCluster available=org.apache.dubbo.rpc.cluster.support.AvailableCluster mergeable=org.apache.dubbo.rpc.cluster.support.MergeableCluster broadcast=org.apache.dubbo.rpc.cluster.support.BroadcastCluster registryaware=org.apache.dubbo.rpc.cluster.support.RegistryAwareCluster
根据Cluster.class定义
@SPI(FailoverCluster.NAME) public interface Cluster { /** * Merge the directory invokers to a virtual invoker. * * @param <T> * @param directory * @return cluster invoker * @throws RpcException */ @Adaptive <T> Invoker<T> join(Directory<T> directory) throws RpcException; }
实际上是获取到的instance是FailoverCluster,经过Cluster$Adaptive的调用,实际上获取到时MockClusterWrapper包装过的FailoverCluster.同理Protocol也是如此。调用顺序如下:
ProtocolFilterWrapper->ProtocolListenerWrapper->QosProtocolWrapper->RegistryProtocol 接下来讲解如何重refProtocol中获取到MockClusterInvoker
在Referenceconfig#createProxy中 invoker = refprotocol.refer(interfaceClass, urls.get(0));会从上面的链中调用最后到RegistryProtocol.refer -> RegistryProtocol.doRefer 直到
Invoker invoker = cluster.join(directory); 这端逻辑就是本文开头所讲的内容。从MockClusterWrapper的join中,我们获取到MockClusterInvoker。
调用
从上一节中我们讲到了InvokerInvocationHandler#invoke,那么实际上就是MockClusterInvoker#invoker
@Override public Result invoke(Invocation invocation) throws RpcException { Result result = null; String value = directory.getUrl().getMethodParameter(invocation.getMethodName(), Constants.MOCK_KEY, Boolean.FALSE.toString()).trim(); if (value.length() == 0 || value.equalsIgnoreCase("false")) { //当没有配置mock,则直接往下调用 服务提供者暴露接口。 result = this.invoker.invoke(invocation); } else if (value.startsWith("force")) { // 有配置强制mock 的化,那么不进行远端调用,而直接调用本地mock实现 if (logger.isWarnEnabled()) { logger.warn("force-mock: " + invocation.getMethodName() + " force-mock enabled , url : " + directory.getUrl()); } //force:direct mock result = doMockInvoke(invocation, null); } else { // 有mock,则当调用服务提供者失败时候,会使用本地mock实现兜底 //fail-mock try { result = this.invoker.invoke(invocation); } catch (RpcException e) { if (e.isBiz()) { throw e; } if (logger.isWarnEnabled()) { logger.warn("fail-mock: " + invocation.getMethodName() + " fail-mock enabled , url : " + directory.getUrl(), e); } result = doMockInvoke(invocation, e); } } return result; }
我们重点看远程服务调用的result = this.invoker.invoke(invocation);那么这个this.invoker是哪个呢? 回到MockClusterWrapper#join,我们直到此时的this.cluster就是failoverCluster,调用其join方法获取到FailoverClusterInvoker
public <T> Invoker<T> join(Directory<T> directory) throws RpcException { return new FailoverClusterInvoker<T>(directory); }
接着执行其MockClusterWrapper#invoke方法 -> AbstractClusterInvoker#invoke -> FailoverClusterInvoker#doInvoke
public Result doInvoke(Invocation invocation, final List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException { List<Invoker<T>> copyInvokers = invokers; // 检查invokers,即检查是否有可用的invokers checkInvokers(copyInvokers, invocation); // 获取方法名 String methodName = RpcUtils.getMethodName(invocation); int len = getUrl().getMethodParameter(methodName, Constants.RETRIES_KEY, Constants.DEFAULT_RETRIES) + 1; if (len <= 0) { len = 1; } // le 为记录最后一次错误。 // retry loop. RpcException le = null; // last exception. List<Invoker<T>> invoked = new ArrayList<Invoker<T>>(copyInvokers.size()); // invoked invokers. Set<String> providers = new HashSet<String>(len); for (int i = 0; i < len; i++) { //Reselect before retry to avoid a change of candidate `invokers`. //NOTE: if `invokers` changed, then `invoked` also lose accuracy. // 为了保证准确性,除第一次外,每次循环,都需要重新检查下invokers的活性 // 一旦某个invoker失活,会被检测到。 if (i > 0) { checkWhetherDestroyed(); copyInvokers = list(invocation); // check again checkInvokers(copyInvokers, invocation); } // 调用负载均衡,选择出某一个invokers Invoker<T> invoker = select(loadbalance, invocation, copyInvokers, invoked); invoked.add(invoker); RpcContext.getContext().setInvokers((List) invoked); try { // 使用选出的invoker,执行invoke方法。 Result result = invoker.invoke(invocation); if (le != null && logger.isWarnEnabled()) { logger.warn("Although retry the method " + methodName + " in the service " + getInterface().getName() + " was successful by the provider " + invoker.getUrl().getAddress() + ", but there have been failed providers " + providers + " (" + providers.size() + "/" + copyInvokers.size() + ") from the registry " + directory.getUrl().getAddress() + " on the consumer " + NetUtils.getLocalHost() + " using the dubbo version " + Version.getVersion() + ". Last error is: " + le.getMessage(), le); } return result; } catch (RpcException e) { if (e.isBiz()) { // biz exception. throw e; } le = e; } catch (Throwable e) { le = new RpcException(e.getMessage(), e); } finally { providers.add(invoker.getUrl().getAddress()); } } throw new RpcException(le.getCode(), "Failed to invoke the method " + methodName + " in the service " + getInterface().getName() + ". Tried " + len + " times of the providers " + providers + " (" + providers.size() + "/" + copyInvokers.size() + ") from the registry " + directory.getUrl().getAddress() + " on the consumer " + NetUtils.getLocalHost() + " using the dubbo version " + Version.getVersion() + ". Last error is: " + le.getMessage(), le.getCause() != null ? le.getCause() : le); }
这边的invoker从debug上来看是这样的 先调用了 RegisterDirectory$InvokerDelegate.invoke(InvokerWrapper.invoke) -> ListenerInvokerWraper.invoke -> ProtocolFilterWrapper.invoke -> DubboInvoke.invoke