Dubbo服务调用过程 笔记

前面消费者提到过代理对象是通过JavassistProxyFactory 动态生成的,所以当调用sayHelloService.sayHello(name);

时,实际上是调用proxy里面的返回的 InvokerInvocationHandler 包装过的,基于前面已经包装过的directory,

现在就是        InvokerInvocationHandler (MockClusterInvoker(FailoverClusterInvoker(directory)))

public class JavassistProxyFactory extends AbstractProxyFactory {
    public JavassistProxyFactory() {
    }

    public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
        return Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
    }

    public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
        final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf(36) < 0 ? proxy.getClass() : type);
        return new AbstractProxyInvoker<T>(proxy, type, url) {
            protected Object doInvoke(T proxy, String methodName, Class<?>[] parameterTypes, Object[] arguments) throws Throwable {
                return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
            }
        };
    }
}

所以入口类就是 InvokerInvocationHandler 在基于上面调调用链一层一层往下

public class InvokerInvocationHandler implements InvocationHandler {
    private static final Logger logger = LoggerFactory.getLogger(InvokerInvocationHandler.class);
    private final Invoker<?> invoker;

    public InvokerInvocationHandler(Invoker<?> handler) {
        this.invoker = handler;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String methodName = method.getName();
        Class<?>[] parameterTypes = method.getParameterTypes();
        if (method.getDeclaringClass() == Object.class) {
            return method.invoke(this.invoker, args);
        } else if ("toString".equals(methodName) && parameterTypes.length == 0) {
            return this.invoker.toString();
        } else if ("hashCode".equals(methodName) && parameterTypes.length == 0) {
            return this.invoker.hashCode();
        } else {
            return "equals".equals(methodName) && parameterTypes.length == 1 ? this.invoker.equals(args[0]) : this.invoker.invoke(new RpcInvocation(method, args)).recreate();
        }
    }
}

当调用service接口的时候就是在调用InvokerInvocationHandler的invoker方法,在invoker方法中会把方法名method和参数args包装成一个RocInvoker对象,此时在调用invoker.invoker就是进入了上面说的包装类中

this.invoker.invoke(new RpcInvocation(method, args)

进入MockClusterInvoker,这是一个降级

public Result invoke(Invocation invocation) throws RpcException {
        Result result = null;
        String value = this.directory.getUrl().getMethodParameter(invocation.getMethodName(), "mock", Boolean.FALSE.toString()).trim();
        if (value.length() != 0 && !value.equalsIgnoreCase("false")) {
            // 是否强制走降级,根据我们的配置
            // 比如服务没准备好,返回测试数据让代码可以走通
            if (value.startsWith("force")) {
                if (logger.isWarnEnabled()) {
                    logger.warn("force-mock: " + invocation.getMethodName() + " force-mock enabled , url : " + this.directory.getUrl());
                }

                result = this.doMockInvoke(invocation, (RpcException)null);
            } else {
                // 远程调用
                try {
                    result = this.invoker.invoke(invocation);
                } catch (RpcException var5) {
                    // 判断是否是业务异常,是就直接抛出
                    if (var5.isBiz()) {
                        throw var5;
                    }
                    // 不是就走降级策略
                    if (logger.isWarnEnabled()) {
                        logger.warn("fail-mock: " + invocation.getMethodName() + " fail-mock enabled , url : " + this.directory.getUrl(), var5);
                    }

                    result = this.doMockInvoke(invocation, var5);
                }
            }
        } else {
            // 不走mock操作
            // 远程调用
            result = this.invoker.invoke(invocation);
        }

        return result;
    }

没有配置mock所以不走mock操作,进入下一个 FailoverClusterInvoker

进入后发现没有invoker方法,老规矩看父类

public class FailoverClusterInvoker<T> extends AbstractClusterInvoker<T> {
    private static final Logger logger = LoggerFactory.getLogger(FailoverClusterInvoker.class);

    public FailoverClusterInvoker(Directory<T> directory) {
        super(directory);
    }

    public Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
        //  tudo
    }
}

进入 AbstractClusterInvoker

public Result invoke(Invocation invocation) throws RpcException {
        this.checkWhetherDestroyed();
        Map<String, String> contextAttachments = RpcContext.getContext().getAttachments();
        if (contextAttachments != null && contextAttachments.size() != 0) {
            ((RpcInvocation)invocation).addAttachments(contextAttachments);
        }
        // 从directory拿到远程调用列表,里面还会有一个根据标签的route
        List<Invoker<T>> invokers = this.list(invocation);
        // 根据我们配置的loadbalance 拿到一个负载均衡策略,默认为random
        // 然后选择invokers其中一个去调用
        LoadBalance loadbalance = this.initLoadBalance(invokers, invocation);
        RpcUtils.attachInvocationIdIfAsync(this.getUrl(), invocation);
        return this.doInvoke(invocation, invokers, loadbalance);
    }

    // 默认返回RandomLoadBalance
 protected LoadBalance initLoadBalance(List<Invoker<T>> invokers, Invocation invocation) {
        return CollectionUtils.isNotEmpty(invokers) ? (LoadBalance)ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(((Invoker)invokers.get(0)).getUrl().getMethodParameter(RpcUtils.getMethodName(invocation), "loadbalance", "random")) : (LoadBalance)ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension("random");
    }

直接进入doInvoke ,这里没有配置容错策略默认是走 FailoverClusterInvoker

public Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
        List<Invoker<T>> copyInvokers = invokers;
        this.checkInvokers(invokers, invocation);
        String methodName = RpcUtils.getMethodName(invocation);
        // 获得重试次数,默认2次,包换直接调用的一共3次
        int len = this.getUrl().getMethodParameter(methodName, "retries", 2) + 1;
        if (len <= 0) {
            len = 1;
        }

        RpcException le = null;
        // 这里保存调用过的invoker,下次重试会排除
        List<Invoker<T>> invoked = new ArrayList(invokers.size());
        Set<String> providers = new HashSet(len);

        for(int i = 0; i < len; ++i) {
            if (i > 0) {
                this.checkWhetherDestroyed();
                copyInvokers = this.list(invocation);
                this.checkInvokers(copyInvokers, invocation);
            }
            // 负载均衡得到一个invoker
            Invoker<T> invoker = this.select(loadbalance, invocation, copyInvokers, invoked);
            invoked.add(invoker);
            RpcContext.getContext().setInvokers(invoked);

            try {
                Result result = invoker.invoke(invocation);
                if (le != null && logger.isWarnEnabled()) {
                   // 省略打印日志
                }

                Result var13 = result;
                return var13;
            } catch (RpcException var18) {
                //  业务异常抛出
                if (var18.isBiz()) {
                    throw var18;
                }

                le = var18;
            } catch (Throwable var19) {
                le = new RpcException(var19.getMessage(), var19);
            } finally {
                providers.add(invoker.getUrl().getAddress());
            }
        }

    }

到了select又进入AbstractClusterInvoker 集合只有一个直接返回,否则进入loadbalance.select

protected Invoker<T> select(LoadBalance loadbalance, Invocation invocation, List<Invoker<T>> invokers, List<Invoker<T>> selected) throws RpcException {
        if (CollectionUtils.isEmpty(invokers)) {
            return null;
        } else {
            String methodName = invocation == null ? "" : invocation.getMethodName();
            boolean sticky = ((Invoker)invokers.get(0)).getUrl().getMethodParameter(methodName, "sticky", false);
            if (this.stickyInvoker != null && !invokers.contains(this.stickyInvoker)) {
                this.stickyInvoker = null;
            }

            if (sticky && this.stickyInvoker != null && (selected == null || !selected.contains(this.stickyInvoker)) && this.availablecheck && this.stickyInvoker.isAvailable()) {
                return this.stickyInvoker;
            } else {
                Invoker<T> invoker = this.doSelect(loadbalance, invocation, invokers, selected);
                if (sticky) {
                    this.stickyInvoker = invoker;
                }

                return invoker;
            }
        }
    }


private Invoker<T> reselect(LoadBalance loadbalance, Invocation invocation, List<Invoker<T>> invokers, List<Invoker<T>> selected, boolean availablecheck) throws RpcException {
        List<Invoker<T>> reselectInvokers = new ArrayList(invokers.size() > 1 ? invokers.size() - 1 : invokers.size());
        Iterator var7 = invokers.iterator();

        while(true) {
            Invoker invoker;
            do {
                do {
                    if (!var7.hasNext()) {
                        if (!reselectInvokers.isEmpty()) {
                            return loadbalance.select(reselectInvokers, this.getUrl(), invocation);
                        }

                        if (selected != null) {
                            var7 = selected.iterator();

                            while(var7.hasNext()) {
                                invoker = (Invoker)var7.next();
                                if (invoker.isAvailable() && !reselectInvokers.contains(invoker)) {
                                    reselectInvokers.add(invoker);
                                }
                            }
                        }

                        if (!reselectInvokers.isEmpty()) {
                            return loadbalance.select(reselectInvokers, this.getUrl(), invocation);
                        }

                        return null;
                    }

                    invoker = (Invoker)var7.next();
                } while(availablecheck && !invoker.isAvailable());
            } while(selected != null && selected.contains(invoker));

            reselectInvokers.add(invoker);
        }
    }

进入 AbstractLoadBalance 的select 在调子类 RandomLoadBalance doSelect

 protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
        int length = invokers.size();
        boolean sameWeight = true;
        int[] weights = new int[length];
        // 权重根据配置和启动时间计算
        int firstWeight = this.getWeight((Invoker)invokers.get(0), invocation);
        weights[0] = firstWeight;
        int totalWeight = firstWeight;

        int offset;
        int i;
        for(offset = 1; offset < length; ++offset) {
            i = this.getWeight((Invoker)invokers.get(offset), invocation);
            weights[offset] = i;
            totalWeight += i;
            if (sameWeight && i != firstWeight) {
                sameWeight = false;
            }
        }
        // 配置的服务权重不一样走这里
        if (totalWeight > 0 && !sameWeight) {
            offset = ThreadLocalRandom.current().nextInt(totalWeight);

            for(i = 0; i < length; ++i) {
                offset -= weights[i];
                if (offset < 0) {
                    return (Invoker)invokers.get(i);
                }
            }
        }
        // 配置的服务权重一样随机返回一个
        return (Invoker)invokers.get(ThreadLocalRandom.current().nextInt(length));
    }

得到一个invoker后返回FailoverClusterInvoker

这里的invoker是之前包装好 InvokerDelegate(ProtocolFilterWrapper(ListenerInvokerWrapper(DubboInvoker)))

跳过过滤连,这里会先进入抽象父类的invoker然后调用doInvoker 直接进入DubboInvoker

public Result invoke(Invocation inv) throws RpcException {
        if (this.destroyed.get()) {
            this.logger.warn("Invoker for service " + this + " on consumer " + NetUtils.getLocalHost() + " is destroyed, , dubbo version is " + Version.getVersion() + ", this invoker should not be used any longer");
        }

        RpcInvocation invocation = (RpcInvocation)inv;
        invocation.setInvoker(this);
        if (CollectionUtils.isNotEmptyMap(this.attachment)) {
            invocation.addAttachmentsIfAbsent(this.attachment);
        }

        Map<String, String> contextAttachments = RpcContext.getContext().getAttachments();
        if (CollectionUtils.isNotEmptyMap(contextAttachments)) {
            invocation.addAttachments(contextAttachments);
        }

        invocation.setInvokeMode(RpcUtils.getInvokeMode(this.url, invocation));
        RpcUtils.attachInvocationIdIfAsync(this.getUrl(), invocation);

        try {
            // 这里调用子类的doInvoker ,也就是DubboInvoker
            return this.doInvoke(invocation);
        } catch (InvocationTargetException var6) {
            Throwable te = var6.getTargetException();
            if (te == null) {
                return AsyncRpcResult.newDefaultAsyncResult((Object)null, var6, invocation);
            } else {
                if (te instanceof RpcException) {
                    ((RpcException)te).setCode(3);
                }

                return AsyncRpcResult.newDefaultAsyncResult((Object)null, te, invocation);
            }
        } catch (RpcException var7) {
            if (var7.isBiz()) {
                return AsyncRpcResult.newDefaultAsyncResult((Object)null, var7, invocation);
            } else {
                throw var7;
            }
        } catch (Throwable var8) {
            return AsyncRpcResult.newDefaultAsyncResult((Object)null, var8, invocation);
        }
    }

DubboInvoker

protected Result doInvoke(Invocation invocation) throws Throwable {
        RpcInvocation inv = (RpcInvocation)invocation;
        String methodName = RpcUtils.getMethodName(invocation);
        inv.setAttachment("path", this.getUrl().getPath());
        inv.setAttachment("version", this.version);
        // 这里是之前构建的链接
        ExchangeClient currentClient;
        if (this.clients.length == 1) {
            currentClient = this.clients[0];
        } else {
            currentClient = this.clients[this.index.getAndIncrement() % this.clients.length];
        }

        try {
            boolean isOneway = RpcUtils.isOneway(this.getUrl(), invocation);
            int timeout = this.getUrl().getMethodPositiveParameter(methodName, "timeout", 1000);
            // 是否存在返回值
            if (isOneway) {
                boolean isSent = this.getUrl().getMethodParameter(methodName, "sent", false);
                currentClient.send(inv, isSent);
                return AsyncRpcResult.newDefaultAsyncResult(invocation);
            } else {
                // 存在走这里
                // 采用异步通信
                AsyncRpcResult asyncRpcResult = new AsyncRpcResult(inv);
                // timeout超时时间
                CompletableFuture<Object> responseFuture = currentClient.request(inv, timeout);
                asyncRpcResult.subscribeTo(responseFuture);
                FutureContext.getContext().setCompatibleFuture(responseFuture);
                return asyncRpcResult;
            }
        } catch (TimeoutException var9) {
            throw new RpcException(2, "Invoke remote method timeout. method: " + invocation.getMethodName() + ", provider: " + this.getUrl() + ", cause: " + var9.getMessage(), var9);
        } catch (RemotingException var10) {
            throw new RpcException(1, "Failed to invoke remote method: " + invocation.getMethodName() + ", provider: " + this.getUrl() + ", cause: " + var10.getMessage(), var10);
        }
    }

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值