文章目录
直接Debug到DubboInvoker中的doInvoke方法,如下:

其中debug中的变量如下:
从代码中看,主要分成三个部分:
一、RpcInvocation的构造
首先把传递进来的 invocation 强制转化为 RpcInvocation 对象,然后设置了分别以“path”和“version”为key的参数,如下:
二、获取信息交换层的ExchangeClient,实例化是ReferenceCountExchangeClient
ReferenceCountExchangeClient会将请求交HeaderExchangeClient处理,不进行任何其他操作。另外HeaderExchangeClient提供心跳检查功能,同时将send、request、close等事件转由HeaderExchangeChannel处理。
三、远程调用
1. 获取本次调用是不是异步调用,放到 isAsync 变量中
通常来说在配置文件中dubbo设置异常调用有以下两种方式
- 第一种:若配置里添加<dubbo:method name=“xxx” async=“true”/>,表示单个方法xxx使用异步方式
- 第二种:若demoService下的所有方法都使用异步,直接配置为<dubbo:reference async=“true”/>
这里看下获取 isAsync 变量的方法,如下:
上面方法中首先判断传递进来的Invocation(已经转化为RpcInvocation)中attachments属性是否包含“async”的key,然后再从方法配置中是否含有async标签(即上面配置方式,默认是false),
那么Invocation是怎么把async设值进去的呢?回顾一下dubbo的方法调用过程,会直接调用 InvokerInvocationHandler 的 invoke 方法,这里先回到调用方法:
首先看方法和它的类中是否同时满足 - 含有 @AsyncFor 注解
- 方法名以“Async”结尾
- 是CompletableFuture类的返回类型
若上面都满足,则构造把异步信息放到RpcInvocation中,若不满足的话,再判断方法返回值的类型是否是CompletableFuture类型,若有,则加入异步信息,否则不做任何处理。
2. 方法返回类型是否是CompletableFuture类型,放到 isAsyncFuture 变量中
判断 RpcInvocation 即inv变量中是参数中是否设置了“future_generated” 和 “future_returntype”的key,通过第1点的分析,两个key设置为true的条件之一是方法返回类型是CompletableFuture类型,所以 isAsyncFuture 变量存放的是调用的方法返回值类型是否 CompletableFuture类型。
3. 判断方法中有没有返回值,默认值是true,放到 isOneWay 变量中
首先从 inv 中参数中获取,然后从url中判断。
4. 获取用户配置的超时时间(timeout标签),若没有设置,就使用默认1s,放到 timeout 变量中
5. 发起调用过程
- 如果方法不需要返回值,不管同步还是异步,请求直接发出,不会创建Future,直接返回RpcResult空对象
- 如果方法是isAsync(异步),则
- 先创建ResponseFuture对象,之后使用FutureAdapter包装该ResponseFuture对象;(创建ResponseFuture对象与同步的代码相同,最后得到的是一个DefaultFuture对象)
- 然后将该FutureAdapter对象设入当前线程的上下文中RpcContext.getContext();
- 最后根据有无CompletableFuture类型的返回值来返回不同的Result(有CompletableFuture类型的返回值,则返回AsyncRpcResult,无则返回SimpleAsyncRpcResult对象实例)
- 如果是同步且有返回值,则先创建ResponseFuture对象,之后直接调用其get()方法进行阻塞调用,直到返回结果后返回。
其中 SimpleAsyncRpcResult 继承于 AsyncRpcResult ,执行构造方法的时候都是调用 AsyncRpcResult 的构造方法,如下:
四、参考
参考dubbo异步调用:https://dubbo.gitbooks.io/dubbo-user-book/content/demos/async-call.html