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
原文地址:https://www.cnblogs.com/kevin-yuan/p/7380858.html