zoukankan      html  css  js  c++  java
  • dubbo源码解析(三) DubboInvoker

    上篇dubbo源码解析(二)中说到创建代理时会通过refprotocol.refer(interfaceClass, urls.get(0))先创建一个invoker对象出来

    以DubboProtocol为例

    public <T> Invoker<T> refer(Class<T> serviceType, URL url) throws RpcException {
            // create rpc invoker.
            DubboInvoker<T> invoker = new DubboInvoker<T>(serviceType, url, getClients(url), invokers);
            invokers.add(invoker);
            return invoker;
        }

    执行refer时,会创建一个DubboInvoker对象返回

    我们再看DubboInvoker这个类

    这个类继承自AbstractInvoker,而AbstractInvoker这个类实现了Invoker接口,也就实现了,invoke方法

    方法如下:

    public Result invoke(Invocation inv) throws RpcException {
            if(destroyed) {
                throw new RpcException("Rpc invoker for service " + this + " on consumer " + NetUtils.getLocalHost() 
                                                + " use dubbo version " + Version.getVersion()
                                                + " is DESTROYED, can not be invoked any more!");
            }
            RpcInvocation invocation = (RpcInvocation) inv;
            invocation.setInvoker(this);
            if (attachment != null && attachment.size() > 0) {
                invocation.addAttachmentsIfAbsent(attachment);
            }
            Map<String, String> context = RpcContext.getContext().getAttachments();
            if (context != null) {
                invocation.addAttachmentsIfAbsent(context);
            }
            if (getUrl().getMethodParameter(invocation.getMethodName(), Constants.ASYNC_KEY, false)){
                invocation.setAttachment(Constants.ASYNC_KEY, Boolean.TRUE.toString());
            }
            RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
            
            
            try {
                return doInvoke(invocation);
            } catch (InvocationTargetException e) { // biz exception
                Throwable te = e.getTargetException();
                if (te == null) {
                    return new RpcResult(e);
                } else {
                    if (te instanceof RpcException) {
                        ((RpcException) te).setCode(RpcException.BIZ_EXCEPTION);
                    }
                    return new RpcResult(te);
                }
            } catch (RpcException e) {
                if (e.isBiz()) {
                    return new RpcResult(e);
                } else {
                    throw e;
                }
            } catch (Throwable e) {
                return new RpcResult(e);
            }
        }

    主要做了三件事

    1. 做了一些初始化操作

    2. 调用了抽象方法 doInvoke(由子类实现)

    3. 捕获了 doInvoke方法的异常,将结果返回

    我们接着看一下DubboInvoker的doInvoke方法

    protected Result doInvoke(final Invocation invocation) throws Throwable {
            RpcInvocation inv = (RpcInvocation) invocation;
            final String methodName = RpcUtils.getMethodName(invocation);
            inv.setAttachment(Constants.PATH_KEY, getUrl().getPath());
            inv.setAttachment(Constants.VERSION_KEY, version);
            
            ExchangeClient currentClient;
            if (clients.length == 1) {
                currentClient = clients[0];
            } else {
                currentClient = clients[index.getAndIncrement() % clients.length];
            }
            try {
                boolean isAsync = RpcUtils.isAsync(getUrl(), invocation);
                boolean isOneway = RpcUtils.isOneway(getUrl(), invocation);
                int timeout = getUrl().getMethodParameter(methodName, Constants.TIMEOUT_KEY,Constants.DEFAULT_TIMEOUT);
                if (isOneway) {
                    boolean isSent = getUrl().getMethodParameter(methodName, Constants.SENT_KEY, false);
                    currentClient.send(inv, isSent);
                    RpcContext.getContext().setFuture(null);
                    return new RpcResult();
                } else if (isAsync) {
                    ResponseFuture future = currentClient.request(inv, timeout) ;
                    RpcContext.getContext().setFuture(new FutureAdapter<Object>(future));
                    return new RpcResult();
                } else {
                    RpcContext.getContext().setFuture(null);
                    return (Result) currentClient.request(inv, timeout).get();
                }
            } catch (TimeoutException e) {
                throw new RpcException(RpcException.TIMEOUT_EXCEPTION, "Invoke remote method timeout. method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e);
            } catch (RemotingException e) {
                throw new RpcException(RpcException.NETWORK_EXCEPTION, "Failed to invoke remote method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e);
            }
        }

    判断与远程交互的客户端,如果是一个,直接用,如果是多个则轮训

    判断接口是单方向的,直接向远端发送请求send(),如果不是,则判断是不是异步的,如果是异步调用将future放到context里,如果是同步则等接口执行完之后get出结果

  • 相关阅读:
    阶段1 语言基础+高级_1-2 -面向对象和封装_2面向对象思想的举例
    阶段1 语言基础+高级_1-2 -面向对象和封装_1面向对象思想的概述
    2-3 【初识组件】顶部 TabBar
    2-2 工程源码文件结构
    Fragment状态保存
    【51单片机】六种亮灯方式
    Hadoop自学笔记(二)HDFS简单介绍
    lvs 负载均衡环境搭建
    [学习笔记—Objective-C]《Objective-C-基础教程 第2版》第十一章 属性
    说说nio----1
  • 原文地址:https://www.cnblogs.com/liguangming/p/9929027.html
Copyright © 2011-2022 走看看