丛林探险之Dubbo远程调用

丛林背景

dubbo框架的核心就是远程调用。在设计上,作者对远程调用的实现进行了分层,一共是三层:business层、rpc层与remoting层。

  • business层,这一层有为RPC接口创建的动态代理对象
  • rpc层,这一层的核心为Invoker链
  • remoting层,封装底层通信细节,如果底层通信走netty4则这一层的核心为: NettyChannel、ChannelHandler链以及dubbo线程池

本文探秘dubbo远程调用中客户端和服务端的行为,咋们这篇不求甚解,只要在脑海中形成清晰的远程调用的流程图即可。

(一)客户端发起远程调用的过程

以下图示是我在客户端发起一次远程调用的客户端调用链截图,整个客户端的调用链比较清晰,三层的界限圈出来了,以下将对每一层进行分析。
在这里插入图片描述

1.1 business层解析

RPC接口的动态代理对象持有了InvokerInvocationHandler对象。InvokerInvocationHandler对象持有了Invoker对象,并将请求委托给Invoker对象来处理。
在这里插入图片描述

1.2 rpc层解析

rpc层上,请求从MockClusterInvoker一直传递给DubboInvoker,可以把这一段看成一个变体的责任链。DubboInvoker位于invoker链的尾部,委托给remoting层来发送tcp请求。
在这里插入图片描述

1.2.1 DubboInvoker

DubboInvoker 委托给ExchangeClient对象来发起请求,请求由此传递到了remoting层,ExchangeClient.request方法返回一个CompletableFuture对象,RPC层通过CompletableFuture对象可以获取到调用的结果。
在这里插入图片描述

1.2.2 AsyncToSyncInvoker

AsyncToSyncInvoker是invoker链中的一个类,在invoker.invoke()方法调用返回之后,他会阻塞在
Future.get()方法中(Result实现了Future接口)直到收到一个响应结果才会接着往下执行。
所以当客户端的业务线程发起远程调用时就会阻塞在这个方法上,直到有响应结果。
在这里插入图片描述

1.3 remoting层解析

remoting层封装底层通信的细节。这次客户端的远程调用请求最终委托给netty4的 NioSocketChannel.writeAndFlush方法。根据netty4的React线程池模型的实现,NioSocketChannel.writeAndFlush方法是会将这次写事件提交给netty的worker线程池来执行。

1.3.1 ExchangeClient

ExchangeClient 负责 RPC层与Remoting层的数据交互,RPC层的数据实体为Invocation,Remoting层的数据实体为Request与Response。在客户端调用过程中ExchangeClient 负责将Invocation封装为Request对象。

1.3.2 NettyChannel

NettyChannel持有一个netty4的NioSocketChannel对象,并调用它的writeAndFlush来发送请求。
在这里插入图片描述

(二)客户端收到服务端响应的过程

客户端的netty worker线程在收到服务端发来的tcp响应包后会封装为一个ChannelEventRunnable对象并提交给DubboClientHandler线程池来处理。ChannelEventRunnable任务就是调用DefaultFuture.complete方法并传入远程调用的结果。

在这里插入图片描述

1.1 DefaultFuture

DefaultFuture继承了CompletableFuture类,这个类在设计上是用来获取远程调用的结果。当DubboClientHandler线程调用DefaultFuture对象的comlete方法并传入远程调用的结果,则阻塞在future.get() 的业务线程就能拿到远程调用的结果,这次调用流程基本就走完了!
在这里插入图片描述

(三)服务端处理请求的过程

以下截图为服务端收到远程调用请求后的调用链,我红框圈出来的是一个channelHandler链,最下层的NettyServerHandler是一个适配器,适配了dubbo自家的ChannelHandler接口并实现了netty4的ChannelHandler接口,由NettyServerHandler这个适配器作为dubbo自家的ChannelHandler链的链首。这个ChannelHandler链的链尾是AllChannelHandler。

在这里插入图片描述
以下截图为dubbo线程池处理上述被提交的任务,并最终调用服务对象的目标方法的调用链截图。
在这里插入图片描述

3.1 remoting层分析
3.1.1 AllChannelHandler

AllChannelHandler作为channelFilter链的尾部,这个地位可想而知。如以下截图所示,他会将TCP请求封装为一个ChannelEventRunnable对象,并分发给dubbo线程池。
在这里插入图片描述

这边还是得额外拓展以下,根据dubbo.protocol.dispatcher的配置不同,可以有以下5种选择,由于我配置的dubbo.protocol.dispatcher=all(默认的配置) 所以这边对应的分发策略为AllChannelHandler,对应这个处理器,worker线程的连接建立事件、连接失效事件、发送数据事件、接受数据事件等都会提交给dubbo线程池来处理。
在这里插入图片描述

3.1.2 HeaderExchangeHandler

HeaderExchangeHandler是一个比较核心的ChannelHandler类,在得到调用的结果之后它会调用NettyChannel.send(res)方法来发送结果。
在这里插入图片描述

3.2 rpc层分析

rpc层就是一个invoker链,重点是最后一个invoker类,就是我红框圈出来的部分 AbstractProxyInvoker
在这里插入图片描述

3.2.1 AbstractProxyInvoker

AbstractProxyInvoker持有了服务对象,并通过反射来调用服务对象的目标方法
在这里插入图片描述
对,这里是结尾,很仓促对不对hhhhhh

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值