Dubbo3.0 Triple协议源码分析
Triple协议基于Http2协议,也就是在使用Triple协议发送数据时,会按HTTP2协议的格式发送,而HTTP2协议相较于HTTP1协议,是HTTP1的升级版,完全兼容HTTP1,而且HTTP2协议从设计层面解决了HTTP1性能低的问题。
Triple的底层原理分析
- UNARY:服务端只有在接收完请求(包括所有HEADERS帧和DATA帧,通过调用onCompleted()发送最后一个DATA帧)之后,才会处理数据,客户端也只有接收完响应包括所有HEADERS帧和DATA帧之后,才会处理响应结果。
- SERVER_STREAM:服务端流,服务端在接收完请求(包括所有DATA帧)之后,才会处理数据。不过在处理数据过程中,可以多次发送响应DATA帧(第一个DATA帧发送之前会发送一个HEADERS帧),客户端每接收到一个响应DATA帧就可以直接处理该响应DATA 帧。这个模式下,客户端只能发一次数据,但能多次处理响应DATA帧。
- BI_STREAM:双端流,或者客户端流,客户端可以控制发送多个请求DATA帧(第一个DATA帧发送之前会发送一个HEADERS帧),服务端会不断的接收请求DATA帧并进行处理,并且及时把处理结果作为响应DATA帧发送给客户端(第一个DATA帧发送之前会发送一个HEADERS帧),而客户端每接收到一个响应结果DATA帧也会直接处理。这种模式下,客户端和服务端都在不断的接收和发送DATA帧并进行处理(注意请求HEADER帧和响应HEADERS帧都只发了一个)。
服务消费端对Triple请求调用和响应处理逻辑
服务消费端请求发送逻辑
服务提供者进行服务导出时,会按照协议以及对应的端口启动Server,比如Triple协议就会启动Netty并绑定指定的端口,等待Socket连接。服务消费端进行服务引入时,会生成TripleInvoker对象,在TripleInvoker对象的构造方法中,会利用ConnectionManager创建一个Connection对象,而Connection对象中包含了一个Bootstrap对象(Netty中用来建立Socket连接的)。不过以上都只是创建对象,并不会真正和服务去建立Socket连接,所以在生成TripleInvoker对象过程中不会真正去创建Socket连接,那什么时候创建的呢?
当我们在服务消费端执行以下代码时

demoService是一个代理对象,在执行方法的过程中,最终会调用TripleInvoker的doInvoke()方法。在doInvoke()方法中,会利用Connection对象来判断Socket连接是否可用,如果不可用并且没有初始化,那就会创建Socket连接。

一个Connection对象表示一个Socket连接,在TripleInvoker对象中也只有一个Connection对象,也就是一个TripleInvoker对象只对应一个Socket连接,这个和DubboInvoker不太一样,一个DubboInvoker中可以有多个ExchangeClient,每个ExchangeClient都会与服务端创建一个Socket连接,所以一个DubboInvoker可以对应多个Socket连接,当然多个Socket连接的目的就是提高并发,不过在TripleInvoker对象中就不需要这么来设计了,因为可以Stream机制来提高并发。
当我们利用服务接口的代理对象执行方法时就会创建一个Socket连接,就算这个代理对象再次执行方法时也不会再次创建Socket连接了,值得注意的是,有可能两个服务接口对应的是一个Socket连接,举个例子:
比如服务提供者A,提供了DemoService和HelloService两个服务,服务消费者B引入了这两个服务,这个两个接口对应的代理对象对应不同的两个TripleInvoker,但是这两个TripleInvoker会共用一个Socket连接,因为ConnectionManager在创建Connection对象时会根据服务URL的address进行缓存,后续这两个代理对象在执行方法时使用的就是同一个Socket连接,但是不同的Stream。
Socket连接创建好后,就需要发送Invocation对象给服务提供者,因为是基于的HTTP2,所以要先创建一个Stream,然后再通过Stream来发送数据。

TripleInvoker用的是Netty,所以最终会利用Netty创建Stream,对应对象为Http2StreamChannel,消费端的TripleInvoker最终会利用Http2StreamChannel发送和接收数据帧,数据帧对应的对象为Http2Frame,它又分为Http2DataFrame、Http2HeadersFrame等具体类型。
正常情况下,会每生成一个数据帧就发送,但是在Triple中有一个批量发送的优化,当发送一个数据帧时,会先把数据帧放入一个WriteQueue中,然后从线程池中拿到一个线程调用WriteQueue的flush方法,该方法的实现为
private void flush() {
try {
QueuedCommand cmd;
int i =

本文详细分析了Triple协议的底层原理,包括服务消费端和提供端的请求调用、响应处理逻辑。Triple基于Http2协议,提供UNARY、SERVER_STREAM和BI_STREAM三种调用模式。在服务消费端,TripleInvoker通过Connection管理Socket连接,并利用Netty的Stream发送和接收数据。服务提供端则通过ServerStream和ServerCall监听器响应请求并发送数据。
最低0.47元/天 解锁文章
289

被折叠的 条评论
为什么被折叠?



