dubbo源码分析-RPC远程调用模块与Remoting通讯模块协作细节

阅读需要技能:

1.设计模式:理解代理模式。JDK动态代理类的使用。
2.设计模式:理解装饰模式。
3.Netty网络通讯编程,server,handler,channel
4.了解Dubbo基本原理,Dubbo模块各层分包关系


Dubbo RPC 服务端提供服务实现细节

服务端提供服务过程主要分为两部分:
暴露服务Exporter(用于向注册中心注册和包装好提供服务的类) 和监听服务(用于打开socket侦听服务,并接收客户端发来的各种请求)

DubboProtocol类被用于服务端和消费端,其分别对应方法export 和refer,是RPC层和REMOTING层的桥梁

下图是暴露服务的执行时序,注意此图不是服务监听执行结果并返回给客户端过程
这里写图片描述

由上图知道两大重要过程,
1是打开socket通讯提供监听客户端请求
2是把暴露的服务注册到注册中心


DubboProtocol如何为服务端打开socket通讯侦听?

细节在DubboProtocol的openserver方法

 private ExchangeServer createServer(URL url) {
  ....
 private ExchangeHandler requestHandler = new ExchangeHandlerAdapter() {
   public Object reply(ExchangeChannel channel, Object message) throws RemotingException {
   ...
    ...}
}
        ExchangeServer server;
             server = Exchangers.bind(url, requestHandler);  
 ....
        return server;
    }

注意requestHandler,这是服务端侦听到请求后由NettyHandler调用的方法


ExchangeHandler requestHandler的使用,服务端侦听到请求后如何回调该方法?

下面补充详细调用过程。注意,在这个过程中,某些功能类在不断在初始化构建,并且有些有装饰模式不断增强功能,这些构建好的包装类,最终在监听接收客户端请求后触发。
DubboProtocol.export(Invoker) line: 253
DubboProtocol.openServer(URL) line: 266
DubboProtocol.createServer(URL) line: 287
Exchangers.bind(URL, ExchangeHandler) line: 63
HeaderExchanger.bind(URL, ExchangeHandler) line: 41

这里写图片描述

装饰模式例子1:

new HeaderExchangeServer(Transporters.bind(url, new DecodeHandler(new HeaderExchangeHandler(handler))));

可见,核心处理类在HeaderExchangeHandler,DecodeHandler是对其包装。Transporters后来被ExtensionLoader默认加载为NettyTransporter,其也包含HeaderExchangeHandler,同理HeaderExchangeServer也包含HeaderExchangeHandler。

这里写图片描述

继续运行调试例子,跳转到下面代码。
装饰模式例子2:
这里写图片描述

new MultiMessageHandler(new HeartbeatHandler(ExtensionLoader.getExtensionLoader(Dispatcher.class)
                                        .getAdaptiveExtension().dispatch(handler, url)));

注意,ExtensionLoader.getExtensionLoader(Dispatcher.class)
.getAdaptiveExtension().dispatch(handler, url)) 生成AllChannelHandler

继续运行调试例子,跳转到下面代码。

这里写图片描述

可见HeaderExchangeHandler(实现ChannelHandler)被传递到NettyServer。
并且NettyServer的doOpen方法内容大部分就是Netty框架的基本应用代码,

 protected void doOpen() throws Throwable {
        ...
      ExecutorService boss = Executors.newCachedThreadPool(new NamedThreadFactory("NettyServerBoss", true));
        ExecutorService worker = Executors.newCachedThreadPool(new NamedThreadFactory("NettyServerWorker", true));
        final NettyHandler nettyHandler = new NettyHandler(getUrl(), this); //this包含requestHandler
       ...
}

回调函数requestHandler被绑定在了Netty框架的监听端,一旦有客户端请求就自动触发,这是Netty框架实现的。
至此,可以看到RPC层如何调用Remoting通讯模块了。本文通讯模块的例子取dubbo默认的Netty网络通讯框架。


DubboProtocol侦听到客户端请求时候究竟执行了什么?

RPC通讯原理就是客户端把请求执行的服务名字,调用方法名,以及方法参数通过socket发送到服务端。服务端利用服务名字反射得到对应的服务类,并且调用服务类的方法,该方法由客户端传送过来指定的方法名,参数内容也是客户端传送过来的参数值。

这个触发执行过程如下:
当有客户端请求时候,
首先DecodeHandler.received进行解码
然后HeaderExchangeHandler.handleRequest一直到NettyHandler的reply方法被触发执行(NettyHandler包装了requestHandler的reply方法),
最后执行完结果后通过channel.send发送结果回客户端。

如图:
reply方法被执行:
这里写图片描述

channel.send发送结果回客户端
这里写图片描述


  • requestHandler的使用,这是服务端侦听到请求后调用的方法(业务处理)
 private ExchangeHandler requestHandler = new ExchangeHandlerAdapter() {
        public Object reply(ExchangeChannel channel, Object message) throws RemotingException {
            if (message instanceof Invocation) {
                Invocation inv = (Invocation) message;
                Invoker<?> invoker = getInvoker(channel, inv);
      ...
       ...
                return invoker.invoke(inv);
            }
        }
}

注意,这里的invoker是代理类代理了真正的服务impl类

  • 然后在代理类JdkProxyFactory或者JavassistProxyFactory的doInvoke(…)方法中执行,因为代理类生成invoker
    Dubbo的invoker.invoke(inv); –> AbstractProxyInvoker的doInvoke(proxy, invocation.getMethodName(), invocation.getParameterTypes(), invocation.getArguments()) –> JdkProxyFactory的doInvoke(…)

总结:

DubboProtocol 利用Netty打开服务端监听操作,绑定Handler,定义Handler业务逻辑
==>
…(省略)
==>
服务端接收用户请求
HeaderExchangeHandler.received
==>
服务端处理用户请求
HeaderExchangeHandler.handleRequest
==>
服务端发送回复到用户
HeaderExchangeChannel.send(response);
==>
使用Netty框架发送
NettyChannel.send
==>
发送端Netty调用:

 ChannelFuture future = channel.write(message); //org.jboss.netty.channel.Channel channel;

延伸思考

基于上面详细的代码调用链指示,相信大家对服务端和消费端如何通过通讯模块交互信息有基本认识。下面问题留给大家思考:

  • DubboProtocol侦听到客户端请求执行完结果后向客户端发送了什么?
  • DubboProtocol客户端如何发送请求?
  • DubboProtocol客户端如何等待服务端应答?
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值