dubbo 问题总结
https://blog.youkuaiyun.com/u010627840/article/details/99305885
1.服务调用在哪里
1.1 消费者调用流程
消费者的调用流程如下(dubbo2.7.3)
proxy0#sayHello(String)
—> InvokerInvocationHandler#invoke(Object, Method, Object[])
—> MockClusterInvoker#invoke(Invocation) // mock 降级
—> AbstractClusterInvoker#invoke(Invocation)
—> FailoverClusterInvoker#doInvoke(Invocation, List<Invoker<T>>, LoadBalance) // 集群容错,负载均衡
—> Filter#invoke(Invoker, Invocation) // 包含多个 Filter 调用
—> ListenerInvokerWrapper#invoke(Invocation)
—> AbstractInvoker#invoke(Invocation)
—> DubboInvoker#doInvoke(Invocation)
—> ReferenceCountExchangeClient#request(Object, int)
—> HeaderExchangeClient#request(Object, int)
—> HeaderExchangeChannel#request(Object, int)
—> AbstractPeer#send(Object)
—> AbstractClient#send(Object, boolean)
—> NettyChannel#send(Object, boolean)
—> NioClientSocketChannel#write(Object)
DubboInvoker 的doInvoke方法(dubbo2.7.3)
首先判断是否为oneWay,也就是单向通信,并获取服务调用超时时间。
DubboInvoker内部默认是异步调用的,但是它的上层封装AsyncToSyncInvoker默认是同步调用的。(dubbo当前为2.7.3)
DubboInvoker的上层Invoker封装为AsyncToSyncInvoker
默认为SYNC模式,如果返回值不是特殊处理的话
invocation.setInvokeMode(RpcUtils.getInvokeMode(url, invocation));
public static InvokeMode getInvokeMode(URL url, Invocation inv) {
if (isReturnTypeFuture(inv)) {
return InvokeMode.FUTURE;
} else if (isAsync(url, inv)) {
return InvokeMode.ASYNC;
} else {
return InvokeMode.SYNC;
}
}
若返回值实现CompletableFuture接口,代表异步处理
public static boolean isReturnTypeFuture(Invocation inv) { Class<?> clazz; if (inv instanceof RpcInvocation) { clazz = ((RpcInvocation) inv).getReturnType(); } else { clazz = getReturnType(inv); } return (clazz != null && CompletableFuture.class.isAssignableFrom(clazz)) || isGenericAsync(inv); }
若指定async为true ,代表异步
public static boolean isAsync(URL url, Invocation inv) { boolean isAsync; if (Boolean.TRUE.toString().equals(inv.getAttachment(ASYNC_KEY))) { isAsync = true; } else { isAsync = url.getMethodParameter(getMethodName(inv), ASYNC_KEY, false); } return isAsync; }
asyncResult.get(Integer.MAX_VALUE, TimeUnit.MILLISECONDS);
这一行代码表面需要强行等待服务端结果返回
@Override public Result invoke(Invocation invocation) throws RpcException { Result asyncResult = invoker.invoke(invocation); try { if (InvokeMode.SYNC == ((RpcInvocation) invocation).getInvokeMode()) { asyncResult.get(Integer.MAX_VALUE, TimeUnit.MILLISECONDS); } } catch (InterruptedException e) { throw new RpcException("Interrupted unexpectedly while waiting for remoting result to return! method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e); }
1.2 异步调用流程图
1) 用户线程调用方法
2) IO线程将请求发送到服务端
3) IO线程setFuture
4) 用户线程执行getFuture获取结果,若为空,通过wait方法等待 .
CompletableFuture,提供了非常强大的Future的扩展功能,可以帮助我们简化异步编程的复杂性,提供了函数式编程的能力,可以通过回调的方式处理计算结果,并且提供了转换和组合CompletableFuture的方法。
5) 服务端响应结果,并写入Future