zoukankan      html  css  js  c++  java
  • Dubbo调用链(version:2.5.3)

    Consumer 调用 Provider的过程:

    (CONSUMER)
    Dubbo服务调用处 --> 调用RPC代理 --> InvokerInvocationHandler#invoke() --> FailoverClusterInvoker#doInvoke() --> ConsumerContextFilter#invoke(Invoker, Invocation) --> DubboCodec#encodeRequestData(Channel channel, ObjectOutput out, Object data) 
    =========》》》(PROVIDER)
    DubboCodec#decodeBody(Channel channel, InputStream is, byte[] header) --> ContextFilter#invoke(Invoker, Invocation) --> ExceptionFilter#invoke(Invoker, Invocation) --> 通过 JavassistProxyFactory#getInvoker() 产生的代理对象来调用真正的Service --> ....反向穿过之前的Filter --> DubboCodec#encodeResponseData(Channel channel, ObjectOutput out, Object data)
    ========》》》(CONSUMER)
    DubboCodec#decodeBody(Channel channel, InputStream is, byte[] header) --> ConsumerContextFilter#invoke(Invoker, Invocation) --> FailoverClusterInvoker#doInvoke() --> InvokerInvocationHandler#invoke() --> 回到调用处

    附:

    Dubbo Provider端(服务端)的异常会放在 RpcResult 中,然后再经过 Provider 端的 ExceptionFilter 处理。
    AbstractProxyInvoker#invoke(Invocation):

    public Result invoke(Invocation invocation) throws RpcException {
            try {
                return new RpcResult(doInvoke(proxy, invocation.getMethodName(), invocation.getParameterTypes(), invocation.getArguments()));
            } catch (InvocationTargetException e) {
                return new RpcResult(e.getTargetException()); // 异常放在 RpcResult 对象中
            } catch (Throwable e) {
                throw new RpcException("Failed to invoke remote proxy method " + invocation.getMethodName() + " to " + getUrl() + ", cause: " + e.getMessage(), e);
            }
    }
    View Code

    Consumer端收到 Provider 端序列化过来的 RpcResult,会调用 RpcResult#recreate(),来还原结果。如果 RpcResult 中有异常,则会 throw 异常

    InvokerInvocationHandler#invoke()
    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(invoker, args);
            }
            if ("toString".equals(methodName) && parameterTypes.length == 0) {
                return invoker.toString();
            }
            if ("hashCode".equals(methodName) && parameterTypes.length == 0) {
                return invoker.hashCode();
            }
            if ("equals".equals(methodName) && parameterTypes.length == 1) {
                return invoker.equals(args[0]);
            }
            return invoker.invoke(new RpcInvocation(method, args)).recreate();  // 得到 Provider 端的结果 RpcResult,然后调用 recreate() 还原结果
        }
    
    RpcResult#recreate()
    public Object recreate() throws Throwable {
            if (exception != null) {
                throw exception;
            }
            return result;
    }
    View Code

    FailoverClusterInvoker#doInvoke()      : dubbo的异常重试逻辑,默认重试2次,表示加上第一次调用,会调用3次

    com.alibaba.dubbo.remoting.exchange.support.DefaultFuture  : Dubbo 获取 Rpc 调用结果的处理

    com.alibaba.dubbo.rpc.protocol.dubbo.DubboCodec    :    Dubbo Request与Response消息的编码、解码处理

    Consumer 调用 Provider 写出的数据包:(DubboCodec.java)

    protected void encodeRequestData(Channel channel, ObjectOutput out, Object data) throws IOException {
            RpcInvocation inv = (RpcInvocation) data;
    
            out.writeUTF(inv.getAttachment(Constants.DUBBO_VERSION_KEY, DUBBO_VERSION));
            out.writeUTF(inv.getAttachment(Constants.PATH_KEY));
            out.writeUTF(inv.getAttachment(Constants.VERSION_KEY));
    
            out.writeUTF(inv.getMethodName());
            out.writeUTF(ReflectUtils.getDesc(inv.getParameterTypes()));
            Object[] args = inv.getArguments();
            if (args != null)
            for (int i = 0; i < args.length; i++){
                out.writeObject(encodeInvocationArgument(channel, inv, i));
            }
            out.writeObject(inv.getAttachments());
        }

    Provider 被调用后回给 Consumer 的数据包:(DubboCodec.java)

    protected void encodeResponseData(Channel channel, ObjectOutput out, Object data) throws IOException {
            Result result = (Result) data;
    
            Throwable th = result.getException();
            if (th == null) {
                Object ret = result.getValue();
                if (ret == null) {
                    out.writeByte(RESPONSE_NULL_VALUE);
                } else {
                    out.writeByte(RESPONSE_VALUE);
                    out.writeObject(ret);
                }
            } else {
                out.writeByte(RESPONSE_WITH_EXCEPTION);
                out.writeObject(th);
            }
    }

    由此可以看出:

    1. Consumer 会向 Provider 传递 attachment

    2. Provider 回给Consumer的只有调用的结果数据或者异常信息

    3. Consumer 端配置优于 Provider 端的配置(因为 Coumer 向 Provider 传递了配置的参数,这是Dubbo 的配置覆盖原则)

    附:

    dubbo 使用细节 : http://www.cnblogs.com/php0368/p/4290791.html

      

    如果想了解更多Dubbo源码的知识,请移步 Dubbo源码解读——通向高手之路 的视频讲解:
    http://edu.51cto.com/sd/2e565
  • 相关阅读:
    document对象补充
    JavaScript(DOM操作)(Window.document对象)
    DOM、Window操作
    JavaScript基础
    格式布局
    洛谷P2756 飞行员配对方案问题
    洛谷P2526 【SHOI2001】小狗散步
    洛谷P1129 【ZJOI2007】矩阵游戏
    洛谷P1640 【SCOI2010】连续攻击游戏
    二分图
  • 原文地址:https://www.cnblogs.com/kevin-yuan/p/7380858.html
Copyright © 2011-2022 走看看