dubbo client发送逻辑探究

最近在阅读dubbo的源码,记录下阅读的一些关键点,本文主要探究dubbo客户端请求发送逻辑;

接口声明及客户端调用方式如下:

public interface DemoService {
    String sayHello(String name);
}

public class Consumer {

    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-consumer.xml"});
        context.start();
        DemoService demoService = (DemoService) context.getBean("demoService"); // get remote service proxy
        String hello = demoService.sayHello("world"); // call remote method
        System.out.println(hello); // get result
    }
}

以dubbo官方demo为例的客户端调用栈:

22. writeAndFlush:244, AbstractChannel (io.netty.channel)
21. send:116, NettyChannel (com.alibaba.dubbo.remoting.transport.netty4)
20. send:336, AbstractClient (com.alibaba.dubbo.remoting.transport)
19. send:58, AbstractPeer (com.alibaba.dubbo.remoting.transport)
18. request:146, HeaderExchangeChannel (com.alibaba.dubbo.remoting.exchange.support.header)
17. request:115, HeaderExchangeClient (com.alibaba.dubbo.remoting.exchange.support.header)
16. request:95, ReferenceCountExchangeClient (com.alibaba.dubbo.rpc.protocol.dubbo)
15. doInvoke:126, DubboInvoker (com.alibaba.dubbo.rpc.protocol.dubbo)
14. invoke:185, AbstractInvoker (com.alibaba.dubbo.rpc.protocol)
13. invoke:86, ListenerInvokerWrapper (com.alibaba.dubbo.rpc.listener)
12. invoke:75, MonitorFilter (com.alibaba.dubbo.monitor.support)
11. invoke:93, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
10. invoke:55, FutureFilter (com.alibaba.dubbo.rpc.protocol.dubbo.filter)
9. invoke:93, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
8. invoke:53, ConsumerContextFilter (com.alibaba.dubbo.rpc.filter)
7. invoke:93, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
6. invoke:59, InvokerWrapper (com.alibaba.dubbo.rpc.protocol)
5. doInvoke:90, FailoverClusterInvoker (com.alibaba.dubbo.rpc.cluster.support)
4. invoke:294, AbstractClusterInvoker (com.alibaba.dubbo.rpc.cluster.support)
3. invoke:84, MockClusterInvoker (com.alibaba.dubbo.rpc.cluster.support.wrapper)
2. invoke:57, InvokerInvocationHandler (com.alibaba.dubbo.rpc.proxy)
1. sayHello:-1, proxy0 (com.alibaba.dubbo.common.bytecode)
main:38, Consumer2 (com.alibaba.dubbo.demo.consumer)

dubbo 虽然现在在经历比较大的版本变迁,但是其核心调用逻辑并未改变,我们在传输层组件netty的writeAndFlush方法加入一个断点得到如上的调用栈
下面进行逐步拆解:

1、 proxy0 是dubbo使用ProxyFactory生成的代理类,默认是 javassist 生成的字节码,具体生成代码逻辑在 com.alibaba.dubbo.common.bytecode.Proxy.getProxy(Class<?>...)

2、InvokerInvocationHandler 代理类的具体处理逻辑,经过代理可以拿到调用接口的方法签名Method及参数,可以参考jdk自带的动态代理来理解

3、MockClusterInvoker是 MockClusterWrapper 创建的 clusterInvoker,而 MockClusterWrapper 是 一个cluster的自动包装(Wrapper)类,dubbo的 spi扩展在初始化的时候会自动寻找 Wrapper 包装在扩展实现上,参考dubbo的 SPI 扩展, MockClusterInvoker 提供了 服务降级和本地伪装的能力, 结合 MockInvokersSelector 实现服务降级,结合 MockProtocol、MockInvoker 实现本地伪装

4-5、FailoverClusterInvoker 是默认的集群容错策略,即失败自动切换策略,值得一提的是 负载均衡器(LoadBalance)也是工作在这个组件下

6、InvokerWrapper 是 Invoker 的增强类,绑定了 URL 信息, 实现了 Node 接口,真实实现还是委托给内部的 Invoker 实例,从构造器上看它并不是一个 SPI Wrapper 类,它是被 RegistryDirectory 手动实例化的

7-12、 ProtocolFilterWrapper$1 是 过滤器(Filter) 链,ProtocolFilterWrapper 是对 Protocol的增强,加入了过滤器功能,他将 filter 数组与 Invoker实现组成一个过滤器链表;同样 ProtocolFilterWrapper 也是一个 Wrapper 包装类,通过 SPI 自动包装在默认的 Protocol 实现类 DubboProtocol 上,与 3 类似

13、ListenerInvokerWrapper 是对Invoker的一个装饰者模式增强,它实现了对invoker的refer及destroy的监听回调,但ListenerInvokerWrapper不是一个 SPI 包装类(Wrapper),因为它没有 Wrapper 类的标志性构造器

14-15、是 DubboInvoker(默认dubbo协议Invoker) 的调用(invoke)逻辑,该方法会调用 ExchangeClient 将请求发出到网络,ExchangeClient 中包括了编码器、序列化组件等初始化逻辑,最终将这些组件设置进netty的 channelhandler,在调用 netty channel的write 方法时会执行具体的编码和序列化

16、ReferenceCountExchangeClient 在 ExchangeClient 的基础上增加了引用计数,在 ExchangeClient 实现共享时提供引用计数,可以为决策关闭 ExchangeClient 时提供依据;

17-18、HeaderExchangeClient 是 Client 的一个装饰者模式增强类,为 Client 增加了心跳逻辑;

19-20、 是 NettyClient 的发送逻辑,委托父类的实现

21、是 NettyClient 的发送逻辑最终委托给 NettyChannel 来实现

22、最终委托给 netty 的 channel.writeAndFlush 实现网络数据的发出,编码和序列化就是在这个过程中执行的,这个就牵涉到netty的使用了不过多解释

47 声望
0 粉丝
0 条评论
推荐阅读
dubbo invoker 浅析
Invoker 是实体域,它是 Dubbo 的核心模型,其它模型都向它靠拢,或转换成它,它代表一个可执行体,可向它发起 invoke 调用,它有可能是一个本地的实现,也可能是一个远程的实现,也可能一个集群实现。

foghost阅读 224

Spring事务传播行为详解
Spring在TransactionDefinition接口中规定了7种类型的事务传播行为。事务传播行为是Spring框架独有的事务增强特性,他不属于的事务实际提供方数据库行为。这是Spring为我们提供的强大的工具箱,使用事务传播行可...

JerryTse242阅读 122.7k评论 97

从零搭建 Node.js 企业级 Web 服务器(十五):总结与展望
总结截止到本章 “从零搭建 Node.js 企业级 Web 服务器” 主题共计 16 章内容就更新完毕了,回顾第零章曾写道:搭建一个 Node.js 企业级 Web 服务器并非难事,只是必须做好几个关键事项这几件必须做好的关键事项就...

乌柏木75阅读 7.1k评论 16

从零搭建 Node.js 企业级 Web 服务器(一):接口与分层
分层规范从本章起,正式进入企业级 Web 服务器核心内容。通常,一块完整的业务逻辑是由视图层、控制层、服务层、模型层共同定义与实现的,如下图:从上至下,抽象层次逐渐加深。从下至上,业务细节逐渐清晰。视图...

乌柏木45阅读 8.5k评论 6

从零搭建 Node.js 企业级 Web 服务器(二):校验
校验就是对输入条件的约束,避免无效的输入引起异常。Web 系统的用户输入主要为编辑与提交各类表单,一方面校验要做在编辑表单字段与提交的时候,另一方面接收表单的接口也要做足校验行为,通过前后端共同控制输...

乌柏木35阅读 6.7k评论 10

一文搞懂秒杀系统,欢迎参与开源,提交PR,提高竞争力。早日上岸,升职加薪。
前言秒杀和高并发是面试的高频考点,也是我们做电商项目必知必会的场景。欢迎大家参与我们的开源项目,提交PR,提高竞争力。早日上岸,升职加薪。知识点详解秒杀系统架构图秒杀流程图秒杀系统设计这篇文章一万多...

王中阳Go33阅读 2.5k评论 1

封面图
从零搭建 Node.js 企业级 Web 服务器(五):数据库访问
回顾 从零搭建 Node.js 企业级 Web 服务器(一):接口与分层,一块完整的业务逻辑是由视图层、控制层、服务层、模型层共同定义与实现的,控制层与服务层实现了业务处理过程,模型层定义了业务实体并以 对象-关系...

乌柏木34阅读 5k评论 9

47 声望
0 粉丝
宣传栏