3.4 Dubbo服务消费端一次远程调用过程
我们先看看整体时序图,如图3.13所示。
图3.13
在3.3节中,我们提到服务消费端通过ReferenceConfig的get()方法返回的是一个代理类,并且方法拦击器为InvokerInvocationHandler,所以当消费方调用了服务的接口方法后会被InvokerInvocationHandler拦截,执行图3.13所示的流程。
在图3.13所示的流程中,步骤1的代码如下:
其中,createInvocation()方法的代码如下:
从上面的代码可知,这里创建了RpcInvocation,其中method为调用的方法,args为参数,这个RpcInvocation对象会一直传递,直到发起远程调用(下面对此会做讲解)。
这里需要注意的一点是,如果服务接口的方法的返回值为CompletableFuture类或者其子类,则需要设置标记future_returntype为true和async=true,这些属性需要设置到附加属性RpcInvocation里:
这些内容在11.2.1小节会做具体讲解。
步骤2和步骤3调用了默认的集群容错策略FailoverClusterInvoker,其内部首先根据设置的负载均衡策略LoadBalance的扩展实现,选择一个invoker作为FailoverClusterInvoker具体的远程调用者,如果调用发生异常,则根据FailoverClusterInvoker的策略重新选择一个invoker进行调用。
在FailoverClusterInvoker内每次调用invoker的invoke()方法时,都会走到步骤8和步骤9,后面的步骤10、步骤11和步骤12是在ProtocolFilterWrapper内创建的责任链,最后调用了原生的DubboInvoker,其使用NettyClient与服务提供者进行交互,其中DubboInvoker的doInvoke()方法的内容如下:
从上面的代码可知,程序首先获取远程调用Client,然后判断调用是否为异步调用、是否请求响应。
如果请求不需要响应结果则直接使用远程Client发起请求调用,然后将RpcContext上下文的future设置为null,并且返回空的RpcResult。
如果请求是异步请求,则保存远程Client发起请求后返回的future对象,并且设置到RpcContext上下文中,这样,调用方就可以通过RpcContext上下文获取该future。
如果请求为同步请求,则首先设置RpcContext上下文中的future对象为null,然后使用远程Client发起请求,然后在返回的future对象上调用get()方法,以同步等待远程调用结果的返回。