客户端:
先简单介绍下一次完整的Dubbo调用所经历的线程阶段。几个信息这里罗列下
- Biz~代表业务线程,即便是业务逻辑处理所处的线程,Biz~线程池可能是业务自己创建维护,大多数的可能是系统框架自身管理的(比如web型的业务系统跑在Tomcat容器下,Biz~线程就是Tomcat维护);IO~代表网络数据处理线程,是IO框架(比如Netty,Grizzly)创建维护,Dubbo Remoting所默认Netty实现是NioEventloopLoopGroup;另外按照Channel与IO线程的绑定关系,也可以直接把IO~看成一个可接受事件消息的Channel。像Biz和IO这样的异步处理阶段在JDK8中有个很精确地抽象描述,叫CompletionStage。
- 大家知道,线程与线程之间做数据通信的方式是共享变量,Biz和IO两个stage之间的数据通信是Queue,具体到Dubbo实现,在客户端一侧的实现(即上图中用1所标注的步骤)中Biz是通过向EventLoop的LinkedBlockingQueue放置一个Task,而EventLoop有对应的Thread会不停的迭代Queue来执行Task中所包含的信息,具体代码可以看SingleThreadEventExecutor(顺便提下,Netty中默认是用无上限的LinkedBlockingQueue,在Biz的速率高于网络速率情况下,似乎好像有Memory Leak的风险)。
- 如上图所示,标准的一次RPC调用经过了图中所示的1,2,3,4的四次消息(事件)传递,分别是客户端业务线程到IO线程的请求发出,服务端IO线程到业务逻辑线程的__请求接受,__服务端处理完成后由业务逻辑线程到IO线程的响应写出,客户端收到结果后从IO线程到业务逻辑的响应处理。除了1与4之间一般需要维护响应和请求的映射对应关系,四次的事件处理都是完全独立的,所以一次RPC调用天然是异步的,而同步是基于异步而来。
客户端异步
实现背景
在Java语言(其他语言不清楚)下一次本地接口的调用可以透明地通过代理机制转为远程RPC的调用,大多数业务方也比较喜欢这种与本地接口类似的编程方式做远程服务集成,所以虽然RPC内部天然是异步的,但