Dubbo3.0Triple协议源码分析

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


  Triple协议基于Http2协议,也就是在使用Triple协议发送数据时,会按HTTP2协议的格式发送,而HTTP2协议相较于HTTP1协议,是HTTP1的升级版,完全兼容HTTP1,而且HTTP2协议从设计层面解决了HTTP1性能低的问题。

Triple的底层原理分析

  1. UNARY:服务端只有在接收完请求(包括所有HEADERS帧和DATA帧,通过调用onCompleted()发送最后一个DATA帧)之后,才会处理数据,客户端也只有接收完响应包括所有HEADERS帧和DATA帧之后,才会处理响应结果。
  2. SERVER_STREAM:服务端流,服务端在接收完请求(包括所有DATA帧)之后,才会处理数据。不过在处理数据过程中,可以多次发送响应DATA帧(第一个DATA帧发送之前会发送一个HEADERS帧),客户端每接收到一个响应DATA帧就可以直接处理该响应DATA 帧。这个模式下,客户端只能发一次数据,但能多次处理响应DATA帧
  3. 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,它又分为Http2DataFrameHttp2HeadersFrame等具体类型。

  正常情况下,会每生成一个数据帧就发送,但是在Triple中有一个批量发送的优化,当发送一个数据帧时,会先把数据帧放入一个WriteQueue中,然后从线程池中拿到一个线程调用WriteQueue的flush方法,该方法的实现为

private void flush() {
   
   
    try {
   
   
        QueuedCommand cmd;
        int i =
### 关于 Dubbo 3.0 的学习笔记与使用教程 #### dubbo-demo 工程结构概述 在探讨 Dubbo 3.0 的具体应用之前,了解其工程构建方式至关重要。dubbo-demo 是 Maven 父工程,而 dubbo-api 则作为 Maven 子模块存在[^1]。此设计模式有助于更好地管理依赖关系和服务接口定义。 #### Dubbo 3.0 新特性介绍 相较于早期版本,Dubbo 3.0 增加了许多新功能来提升性能并简化开发流程。这些改进包括但不限于: - **协议优化**:引入了更高效的通信机制; - **API 变化**:调整了一些核心 API 设计以适应现代微服务体系架构需求; - **配置增强**:提供了更加灵活多样的配置选项和支持多种格式的外部化配置文件; #### 实际案例分析 - HTTP 调用实现 为了加深理解,在实际项目 `dubbo-http` 中实现了通过 HTTP 协议访问远程服务的功能。这里的关键在于如何正确设置 URL 映射以及处理请求参数传递等问题。例如,在 com.crossoverJie.api.DemoApi 接口中定义了一个名为 readMsg 的方法用于接收来自客户端的消息,并接受一个 Map 类型的对象 parames 来携带附加数据[^5]。 ```java public interface DemoApi { String readMsg(Map<String, Object> params); } ``` #### 安全性考量 当涉及到网络传输时,安全性始终是一个不可忽视的话题。因此,在真实环境中部署此类应用程序时,建议采用 SSL/TLS 加密技术或其他适当措施确保敏感信息的安全交换。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

paopaodog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值