乐趣区

关于后端: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 的应用了不过多解释

退出移动版