Dubbo3Triple协议简介与选型思考
Dubbo3 提供了 Triple(Dubbo3)、Dubbo2 协议,这是 Dubbo 框架的原⽣协议。除此之外,Dubbo3 也对众多第三⽅协议进⾏了集成,并将它们纳⼊ Dubbo 的编程与服务治理体系, 包括 gRPC、Thrift、JsonRPC、Hessian2、REST 等。以下重点介绍 Triple 与Dubbo2 协议。
下⼀代 RPC 协议 - Triple
Triple 协议是 Dubbo3 推出的主⼒协议。Triple 意为第三代,通过 Dubbo1.0/ Dubbo2.0 两代协议的演进,以及云原⽣带来的技术标准化浪潮,Dubbo3 新协议 Triple 应运⽽⽣。
R PC 协议简介
协议是 RPC 的核⼼,它规范了数据在⽹络中的传输内容和格式。除必须的请求、响应数据外,通常还会包含额外控制数据,如单次请求的序列化⽅式、超时时间、压缩⽅式和鉴权信息等。
协议的内容包含三部分:
数据交换格式:定义 RPC 的请求和响应对象在⽹络传输中的字节流内容,也叫作序列化⽅式;
协议结构:定义包含字段列表和各字段语义以及不同字段的排列⽅式;
协议通过定义规则、格式和语义来约定数据如何在⽹络间传输。⼀次成功的 RPC 需要通信的两端都能够按照协议约定进⾏⽹络字节流的读写和对象转换。如果两端对使⽤的协议不能达成⼀致,就会出现鸡同鸭讲,⽆法满⾜远程通信的需求。
RPC 协议的设计需要考虑以下内容:
通⽤性:统⼀的⼆进制格式,跨语⾔、跨平台、多传输层协议⽀持
扩展性:协议增加字段、升级、⽀持⽤户扩展和附加业务元数据
性能:As fast as it can be
穿透性:能够被各种终端设备识别和转发:⽹关、代理服务器等 通⽤性和⾼性能通常⽆法同时达到,需要协议设计者进⾏⼀定的取舍HT T P/1.1
⽐于直接构建于 TCP 传输层的私有 RPC 协议,构建于 HTTP 之上的远程调⽤解决⽅案会有更好的通⽤性,如WebServices 或 REST 架构,使⽤ HTTP + JSON 可以说是⼀个事实标准的解决⽅案。
选择构建在 HTTP 之上,有两个最⼤的优势:
HTTP 的语义和可扩展性能很好的满⾜ RPC 调⽤需求。
通⽤性,HTTP 协议⼏乎被⽹络上的所有设备所⽀持,具有很好的协议穿透性。
但也存在⽐较明显的问题:
典型的 Request – Response 模型,⼀个链路上⼀次只能有⼀个等待的 Request 请求。会产⽣ HOL。
Human Readable Headers,使⽤更通⽤、更易于⼈类阅读的头部传输格式,但性能相当差
⽆直接 Server Push ⽀持,需要使⽤ Polling Long-Polling 等变通模式
g RPC
上⾯提到了在 HTTP 及 TCP 协议之上构建 RPC 协议各⾃的优缺点,相⽐于 Dubbo 构建于 TCP 传输层之上,Google 选择将 gRPC 直接定义在 HTTP/2 协议之上。gRPC 的优势由 HTTP2 和 Protobuf 继承⽽来。
基于 HTTP2 的协议⾜够简单,⽤户学习成本低,天然有 server push / 多路复⽤ / 流量控制能⼒
基于 Protobuf 的多语⾔跨平台⼆进制兼容能⼒,提供强⼤的统⼀跨语⾔能⼒
基于协议本⾝的⽣态⽐较丰富,K8s / etcd 等组件的天然⽀持协议,云原⽣的事实协议标准
但是也存在部分问题
对服务治理的⽀持⽐较基础,更偏向于基础的 RPC 功能,协议层缺少必要的统⼀定义,对于⽤户⽽⾔直接⽤起来并不容易。
强绑定 protobuf 的序列化⽅式,需要较⾼的学习成本和改造成本,对于现有的偏单语⾔的⽤户⽽⾔,迁移成本不可忽视
Tr iple 选型的思考
最终我们选择了兼容 gRPC ,以 HTTP2 作为传输层构建新的协议,也就是 Triple。容器化应⽤程序和微服务的兴起促进了针对负载内容优化技术的发展。客户端中使⽤的传统通信协议( RESTFUL或其他基于 HTTP 的⾃定义协议)难以满⾜应⽤在性能、可维护性、扩展性、安全性等⽅便的需求。⼀个跨语⾔、模块化的协议会逐渐成为新的应⽤开发协议标准。⾃从 2017 年 gRPC 协议成为 CNCF 的项⽬后,包括 K8s、etcd 等越来越多的基础设施和业务都开始使⽤ gRPC 的⽣态,作为云原⽣的微服务化框架, Dubbo 的新协议也完美兼容了 gRPC。并且,对于 gRPC 协议中⼀些不完善的部分, Trip
le 也将进⾏增强和补充。那么,Triple 协议是否解决了上⾯我们提到的⼀系列问题呢?
性能上: Triple 协议采取了 metadata 和 payload 分离的策略,这样就可以避免中间设备,如⽹关进⾏ payload 的解析和反序列化,从⽽降低响应时间。
路由⽀持上,由于 metadata ⽀持⽤户添加⾃定义 header ,⽤户可以根据 header 更⽅便的划分集或者进⾏路由,这样发布的时候切流灰度或容灾都有了更⾼的灵活性。
安全性上,⽀持双向 TLS 认证(mTLS)等加密传输能⼒。
易⽤性上,Triple 除了⽀持原⽣ gRPC 所推荐的 Protobuf 序列化外,使⽤通⽤的⽅式⽀持了 Hessian / JSON 等其他序列化,能让⽤户更⽅便的升级到 Triple 协议。对原有的 Dubbo 服务⽽⾔,修改或增加 Triple 协议 只需要在声明服务的代码块添加⼀⾏协议配置即可,改造成本⼏乎为 0。
现状
1、完整兼容 gRPC、客户端/服务端可以与原⽣ gRPC 客户端打通
2、⽬前已经经过⼤规模⽣产实践验证,达到⽣产级别
特点与优势
1、具备跨语⾔互通的能⼒,传统的多语⾔多 SDK 模式和 Mesh 化跨语⾔模式都需要⼀种更通⽤易扩展的数据传输格式。
2、提供更完善的请求模型,除了 Request/Response 模型,还应该⽀持 Streaming 和 Bidirectional。
3、易扩展、穿透性⾼,包括但不限于 Tracing / Monitoring 等⽀持,也应该能被各层设备识别,⽹关设施等可以识别数据报⽂,对Service Mesh 部署友好,降低⽤户理解难度。
4、多种序列化⽅式⽀持、平滑升级。
5、⽀持 Java ⽤户⽆感知升级,不需要定义繁琐的 IDL ⽂件,仅需要简单的修改协议名便可以轻松升级到 Triple 协议。
Tr iple 协议简介
基于 gRPC 协议进⾏进⼀步扩展
Service-Version → “tri-service-version” {Dubbo service version}
Service-Group → “tri-service-group” {Dubbo service group}
Tracing-ID → “tri-trace-traceid” {tracing id}
Tracing-RPC-ID → “tri-trace-rpcid” {_span id _}
Cluster-Info → “tri-unit-info” {cluster infomation}
其中 Service-Version 跟 Service-Group 分别标识了 Dubbo 服务的 version 跟 group 信息,因为 grpc 的 path 申明了 service name 跟 method name,相⽐于 Dubbo 协议,缺少了 version 跟 group 信息;Tracing-ID、Tracing-RPC-ID ⽤于全链路追踪能⼒,分别表⽰ tracing id 跟 span id 信息;Cluster-Info 表⽰集信息,可以使⽤其构建⼀些如集划分等路由相关的灵活的服务治理能⼒。
T r ip le Str e am ing
Triple 协议相⽐传统的 unary ⽅式,多了⽬前提供的 Streaming RPC 的能⼒
Streaming ⽤于什么场景呢?
thrift在⼀些⼤⽂件传输、直播等应⽤场景中, consumer 或 provider 需要跟对端进⾏⼤量数据的传输,由于这些情况下的数据量是⾮常⼤的,因此是没有办法可以在⼀个 RPC 的数据包中进⾏传输,因此对于这些数据包我们需要对数据包进⾏分⽚之后,通过多次 RPC 调⽤进⾏传输,如果我们对这些已经拆分了的 RPC 数据包进⾏并⾏传输,那么到对端后相关的数据包是⽆序的,需要对接收到的数据进⾏排序拼接,相关的逻辑会⾮常复杂。但如果我们对拆分了的 RPC 数据包进⾏串⾏传输,那么对应的⽹络传输 RTT 与数据处理的时延会是⾮常⼤的。
为了解决以上的问题,并且为了⼤量数据的传输以流⽔线⽅式在 consumer 与 provider 之间传输,因此 Streaming RPC 的模型应运⽽⽣。
通过 Triple 协议的 Streaming RPC ⽅式,会在 consumer 跟 provider 之间建⽴多条⽤户态的长连接,Stream。同⼀个 TCP 连接之上能同时存在多个 Stream,其中每条 Stream 都有 StreamId 进⾏标识,对于⼀条 Stream 上的数据包会以顺序⽅式读写。
总结
在 API 领域,最重要的趋势是标准化技术的崛起。Triple 协议是 Dubbo3 推出的主⼒协议。它采⽤分层设计,其数据交换格式基于Protobuf (Protocol Buffers) 协议开发,具备优秀的序列化/反序列化效率,当然还⽀持多种序列化⽅式,也⽀持众多开发语⾔。在传输层协议,Triple 选择了 HTTP/2,相较于 HTTP/1.1,其传输效率有了很⼤提升。此外 HTTP/2 作为⼀个成熟的开放标准,具备丰富的安全、流控等能⼒,同时拥有良好的互操作性。Triple 不仅可以⽤于 Server 端服务调⽤,也可以⽀持浏览器、移动 App 和 IoT 设备与后端服务的交互,同时 Triple协议⽆缝⽀持 Dubbo3 的全部服务治理能⼒。
在 Cloud Native 的潮流下,跨平台、跨⼚商、跨环境的系统间互操作性的需求必然会催⽣基于开放标准的 RPC 技术,⽽ gRPC 顺应了历史趋势,得到了越来越⼴泛地应⽤。在微服务领域,Triple 协议的提出与落地,是 Dubbo3 迈向云原⽣微服务的⼀⼤步。
附录:Dubbo2 Protocol SPEC
Pr o to c o l SPEC!
Magic - Magic High & Magic Low (16 bits)Identifies dubbo protocol with value: 0xdabb
Req/Res (1 bit)Identifies this is a request or response. Request - 1; Response - 0.
2 Way (1 bit)Only useful when Req/Res is 1 (Request), expect for a return value from server or not. Set to 1 if need a
return value from server.
Event (1 bit)Identifies an event message or not, for example, heartbeat event. Set to 1 if this is an event.
Serialization ID (5 bit)Identifies serialization type: the value for fastjson is 6.
Status (8 bits)Only useful when Req/Res is 0 (Response), identifies the status of response
20 - OK
30 - CLIENT_TIMEOUT
31 - SERVER_TIMEOUT
40 - BAD_REQUEST
50 - BAD_RESPONSE
60 - SERVICE_NOT_FOUND
70 - SERVICE_ERROR
80 - SERVER_ERROR
90 - CLIENT_ERROR
100 - SERVER_THREADPOOL_EXHAUSTED_ERROR
Request ID (64 bits)Identifies an unique request. Numeric (long).
Data Length (32)Length of the content (the variable part) after serialization, counted by bytes. Numeric (integer).
Variable PartEach part is a byte[] after serialization with specific serialization type, identifies by Serialization ID.
Every part is a byte[] after serialization with specific serialization type, identifies by Serialization ID
1. If the content is a Request (Req/Res = 1), each part consists of the content, in turn is:
Dubbo version
Service name
Service version
Method name
Method parameter types
Method arguments
Attachments
2. If the content is a Response (Req/Res = 0), each part consists of the content, in turn is:
Return value type, identifies what kind of value returns from server side: RESPONSE_NULL_VALUE - 2,
RESPONSE_VALUE - 1, RESPONSE_WITH_EXCEPTION - 0.
Return value, the real value returns from server.
注意: 对于 (Variable Part) 变长部分,当前版本的 dubbo 框架使⽤ json 序列化时,在每部分内容间额外增加了换⾏符作为分隔,请选⼿在 Variable Part 的每个 part 后额外增加换⾏符, 如:
Dubbo version bytes (换⾏符)
Service name bytes  (换⾏符)
...

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。