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);
}
}

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;
}

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

Dubbo调用链(version:2.5.3)的更多相关文章

  1. dubbo+zipkin调用链监控(二)

    *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...

  2. 调用链系列三、基于zipkin调用链封装starter实现springmvc、dubbo、restTemplate等实现全链路跟踪

    一.实现思路 1.过滤器实现思路 所有调用链数据都通过过滤器实现埋点并收集.同一条链共享一个traceId.每个节点有唯一的spanId. 2.共享传递方式 1.rpc调用:通过隐式传参.dubbo有 ...

  3. dubbo+zipkin调用链监控

    分布式环境下,对于线上出现问题往往比单体应用要复杂的多,原因是前端的一个请求可能对应后端多个系统的多个请求,错综复杂. 对于快速问题定位,我们一般希望是这样的: 从下到下关键节点的日志,入参,出差,异 ...

  4. 使用docker-compose 一键部署你的分布式调用链跟踪框架skywalking

    一旦你的程序docker化之后,你会遇到各种问题,比如原来采用的本地记日志的方式就不再方便了,虽然你可以挂载到宿主机,但你使用 --scale 的话,会导致 记录日志异常,所以最好的方式还是要做日志中 ...

  5. 调用链系列一、Zipkin架构介绍、Springboot集承(springmvc,HttpClient)调用链跟踪、Zipkin UI详解

    1.Zipkin是什么 Zipkin分布式跟踪系统:它可以帮助收集时间数据,解决在microservice架构下的延迟问题:它管理这些数据的收集和查找:Zipkin的设计是基于谷歌的Google Da ...

  6. 部署你的分布式调用链跟踪框架skywalking

    使用docker-compose 一键部署你的分布式调用链跟踪框架skywalking https://www.cnblogs.com/huangxincheng/p/9666930.html 一旦你 ...

  7. .Net Core 商城微服务项目系列(十):使用SkyWalking构建调用链监控(2019-02-13 13:25)

    SkyWalking的安装和简单使用已经在前面一篇介绍过了,本篇我们将在商城中添加SkyWalking构建调用链监控. 顺带一下怎么把ES设置为Windows服务,cd到ES的bin文件夹,运行ela ...

  8. 五分钟后,你将学会在SpringBoot项目中如何集成CAT调用链

    买买买结算系统 一年一度的双十一购物狂欢节就要到了,又到剁手党们开始表演的时刻了.当我们把种草很久的商品放入购物车以后,点击"结算"按钮时,就来到了买买买必不可少的结算页面了.让我 ...

  9. Zipkin存储Sleuth信息实现调用链追踪的几种方法

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/alva_xu/article/detail ...

随机推荐

  1. sql 拼接同列的值

    sql中有时需要将列的值转成行的形式,比如下面的数据,具有相同Path的ZumenID有哪一些,该怎么做呢? 常见的做法可以参见这篇文章http://www.cnblogs.com/xiashengw ...

  2. MFC函数—— CFrameWnd::OnCreateClient

    CFrameWnd::OnCreateClient virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs,CCreateContext*pContext); ...

  3. linux 木马清理过程

    服务器出现异常,完全无法访问,ssh登陆都极其缓慢 解决过程 top 查看系统状态,发现 load average 平均负载值非常高,再看排名第一的进程,是一个不认识的进程名:minerd 感觉是被入 ...

  4. C#中二进制和流之间的各种相互转换

    一. 二进制转换成图片间的转换 1 2 3 4 5 MemoryStream ms = new MemoryStream(bytes); ms.Position = 0; Image img = Im ...

  5. ajax操作之操作 JavaScript 对象

    通过请求获取充分格式化的HTML虽然很方便,但这也意味着必须在传输文本内容的同时也 传输很多HTML标签.有时候,我们希望能够尽量少传输一些数据,然后马上处理这些数据.在 这种情况,我们希望取得能够通 ...

  6. [hadoop读书笔记] 第一章 初识 Hadoop

    P3-P4: 目前遇见的问题很简单:硬盘容量不断提升,1TB的已成为主流,然而数据传输速度从1990年的4.4MB/s仅上升到当前约100MB/s 读取一个1TB的硬盘数据需要耗时至少2.5个小时.写 ...

  7. Linux的内存管理

    Linux的内存管理,实际上跟windows的内存管理有很相像的地方,都是用虚拟内存这个的概念,说到这里不得不骂MS,为什么在很多时候还有很大的物理内存的时候,却还是用到了pagefile. 所以才经 ...

  8. C语言中的运算和运算符

    一.运算符的优先级和结合性 1,优先级 运算符一览表中,运算符越靠上,优先级越高. 2,结合性 假如用O表示需要两个操作数的双目运算符,那么对于表达式aObOc: 左结合运算符会将表达式解释为  (a ...

  9. Eclipse初次java开发问题总结-4-Maven使用问题汇总

    Non-resolvable parent POM [INFO] Scanning for projects... [ERROR] The build could not read 1 project ...

  10. TPshop下载安装

    一. 首先 修改 C:\Windows\System32\drivers\etc\hosts 文件 加一行 127.0.0.1 www.tpshop.com // 这里可以改成你想要的域名 二. 修改 ...