Dubbo 在跨语言和协议穿透性方向的探索:支持 HTTP/2 gRPC

本文探讨了Dubbo在跨语言和协议穿透性上的探索,特别是对HTTP/2和gRPC的支持。Dubbo通过支持gRPC和Protobuf,提升了协议通用性和穿透性,减少了对网关的依赖,同时增强了服务治理和跨语言兼容性。文章通过实例展示了如何在Dubbo中使用gRPC协议和服务定义,以及如何进行跨语言的序列化。未来,Dubbo的目标是实现不同微服务体系间的互通和协议互调。
摘要由CSDN通过智能技术生成

本文整理自刘军在 Dubbo meetup 成都站分享的《Dubbo 在多语言和协议穿透性方向上的探索》。

本文总体上可分为基础产品简介、Dubbo 对 gRPC (HTTP/2) 和 Protobuf 的支持及示例演示三部分,在简介部分介绍了 Dubbo、HTTP/2、gRPC、Protobuf 的基本概念和特点;第二部分介绍了 Dubbo 为何要支持 gRPC (HTTP/2) 和 Protobuf,以及这种支持为 gRPC 和 Dubbo 开发带来的好处与不同;第三部分通过两个实例分别演示了 Dubbo gRPC 和 Dubbo Protobuf 的使用方式。

基本介绍

Dubbo 协议

从协议层面展开,以下是当前 2.7 版本支持的 Dubbo 协议:

众所周知,Dubbo 协议是直接定义在 TCP 传输层协议之上,由于 TCP 高可靠全双工的特点,为 Dubbo 协议的定义提供了最大的灵活性,但同时也正是因为这样的灵活性,RPC 协议普遍都是定制化的私有协议,Dubbo 同样也面临这个问题。在这里我们着重讲一下 Dubbo 在协议通用性方面值得改进的地方,关于协议详细解析请参见官网博客。

Dubbo 协议体 Body 中有一个可扩展的 attachments 部分,这给 RPC 方法之外额外传递附加属性提供了可能,是一个很好的设计。但是类似的 Header 部分,却缺少类似的可扩展 attachments,这点可参考 HTTP 定义的 Ascii Header 设计,将 Body Attachments 和 Header Attachments 做职责划分。
Body 协议体中的一些 RPC 请求定位符如 Service Name、Method Name、Version 等,可以提到 Header 中,和具体的序列化协议解耦,以更好的被网络基础设施识别或用于流量管控。
扩展性不够好,欠缺协议升级方面的设计,如 Header 头中没有预留的状态标识位,或者像 HTTP 有专为协议升级或协商设计的特殊 packet。
在 Java 版本的代码实现上,不够精简和通用。如在链路传输中,存在一些语言绑定的内容;消息体中存在冗余内容,如 Service Name 在 Body 和 Attachments 中都存在。

HTTP/1

相比于直接构建与 TPC 传输层的私有 RPC 协议,构建于 HTTP 之上的远程调用解决方案会有更好的通用性,如WebServices 或 REST 架构,使用 HTTP + JSON 可以说是一个事实标准的解决方案。

之所有选择构建在 HTTP 之上,我认为有两个最大的优势:
HTTP 的语义和可扩展性能很好的满足 RPC 调用需求。
通用性,HTTP 协议几乎被网络上的所有设备所支持,具有很好的协议穿透性。

具体来说,HTTP/1 的优势和限制是:

典型的 Request – Response 模型,一个链路上一次只能有一个等待的 Request 请求
HTTP/1 支持 Keep-Alive 链接,避免了链接重复创建开销
Human Readable Headers,使用更通用、更易于人类阅读的头部传输格式
无直接 Server Push 支持,需要使用 Polling Long-Polling 等变通模式

HTTP/2

HTTP/2 保留了 HTTP/1 的所有语义,在保持兼容的同时,在通信模型和传输效率上做了很大的改进。

支持单条链路上的 Multiplexing,相比于 Request - Response 独占链路,基于 Frame 实现更高效利用链路
Request - Stream 语义,原生支持 Server Push 和 Stream 数据传输
Flow Control,单条 Stream 粒度的和整个链路粒度的流量控制
头部压缩 HPACK
Binary Frame
原生 TLS 支持

gRPC

上面提到了在 HTTP 及 TCP 协议之上构建 RPC 协议各自的优缺点,相比于 Dubbo 构建于 TPC 传输层之上,Google 选择将 gRPC 直接定义在 HTTP/2 协议之上,关于 gRPC 的 基本介绍和 设计愿景 请参考以上两篇文章,我这里仅摘取设计愿景中几个能反映 gRPC 设计目的特性来做简单说明。

gRPC 的基本介绍:
https://platformlab.stanford.edu/Seminar Talks/gRPC.pdf
设计愿景:
https://grpc.io/blog/principles/?spm=ata.13261165.0.0.2be55017XbUhs8

Coverage & Simplicity,协议设计和框架实现要足够通用和简单,能运行在任何设备之上,甚至一些资源首先的如 IoT、Mobile 等设备。
Interoperability & Reach,要构建在更通用的协议之上,协议本身要能被网络上几乎所有的基础设施所支持。
General Purpose & Performant,要在场景和性能间做好平衡,首先协议本身要是适用于各种场景的,同时也要尽量有高的性能。
Payload Agnostic,协议上传输的负载要保持语言和平台中立。
Streaming,要支持 Request - Response、Request - Stream、Bi-Steam 等通信模型。
Flow Control,协议自身具备流量感知和限制的能力。
Metadata Exchange,在 RPC 服务定义之外,提供额外附加数据传输的能力。

总的来说,在这样的设计理念指导下,gRPC 最终被设计为一个跨语言、跨平台的、通用的、高性能的、基于 HTTP/2 的 RPC 协议和框架。

Protobuf

Protocol buffers (Protobuf) 是 Google 推出的一个跨平台、语言中立的结构化数据描述和序列化的产品,它定义了一套结构化数据定义的协议,同时也提供了相应的 Compiler 工具,用来将语言中立的描述转化为相应语言的具体描述。

Protocol buffers (Protobuf) 详情参考:
https://developers.google.com/protocol-buffers/docs/overview

Compiler 详情参考:
https://github.com/protocolbuffers/protobuf/releases/tag/v3.10.0

它的一些特性包括:
跨语言 跨平台,语言中立的数据描述格式,默认提供了生成多种语言的 Compiler 工具。
安全性,由于反序列化的范围和输出内容格式都是 Compiler 在编译时预生成的,因此绕过了类似 Java Deserialization Vulnarability 的问题。
二进制 高性能
强类型
字段变更向后兼容
message Person {
required string name = 1;
required int32 id = 2;
optional string email = 3;

  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {
    required string number = 1;
    optional PhoneType type = 2 [default = HOME];
  }

  repeated PhoneNumber phone = 4;
}

除了结构化数据描述之外,Protobuf 还支持定义 RPC 服务,它允许我们定义一个 .proto 的服务描述文件,进而利用 Protobuf Compiler 工具生成特定语言和 RPC 框架的接口和 stub。后续将要具体讲到的 gRPC + Protobuf、Dubbo-gRPC + Protobuf 以及 Dubbo + Protobuf 都是通过定制 Compiler 类实现的。
service SearchService {
rpc Search (SearchRequest) returns (SearchResponse);
}

Dubbo 所做的支持

跨语言的服务开发涉及到多个方面,从服务定义、RPC 协议到序列化协议都要做到语言中立,同时还针对每种语言有对应的 SDK 实现。虽然得益于社区的贡献,现在 Dubbo 在多语言 SDK 实现上逐步有了起色,已经提供了包括 Java, Go, PHP, C#, Python, NodeJs, C 等版本的客户端或全量实现版本,但在以上提到的跨语言友好型方面,以上三点还是有很多可改进之处。
协议,上面我们已经分析过 Dubbo 协议既有的缺点,如果能在 HTTP/2 之上构建应用层协议,则无疑能避免这些弊端,同时最大可能的提高协议的穿透性,避免网关等协议转换组件的存在,更有利于链路上的流量管控。考虑到 gRPC 是构建在 HTTP/2 之上,并且已经是云原生领域推荐的通信协议,Dubbo 在第一阶段选择了直接支持 gRPC 协议作为当前的 HTTP/2 解决方案。我们也知道 gRPC 框架自身的弊端在于易用性不足以及服务治理能力欠缺(这也是目前绝大多数厂商不会直接裸用 gRPC 框架的原因),通过将其集成进 Dubbo 框架,用户可以方便的使用 Dubbo 编程模型 + Dubbo 服务治理 + gRPC 协议通信的组合。
服务定义,当前 Dubbo 的服务定义和具体的编程语言绑定,没有提供一种语言中立的服务描述格式,比如 Java 就是定义 Interface 接口,到了其他语言又得重新以另外的格式定义一遍。因此 Dubbo 通过支持 Protobuf 实现了语言中立的服务定义。
序列化,Dubbo 当前支持的序列化包括 Json、Hessian2、Kryo、FST、Java 等,而这其中支持跨语言的只有 Json、Hessian2,通用的 Json 有固有的性能问题,而 Hessian2 无论在效率还是多语言 SDK 方面都有所欠缺。为此,Dubbo 通过支持 Protobuf 序列化来提供更高效、易用的跨语言序列化方案。

示例

示例 1,使用 Dubbo 开发 gRPC 服务

gRPC 是 Google 开源的构建在 HTTP/2 之上的一个 PRC 通信协议。Dubbo 依赖其灵活的协议扩展机制,增加了对 gRPC (HTTP/2) 协议的支持。

目前的支持限定在 Dubbo Java 语言版本,后续 Go 语言或其他语言版本将会以类似方式提供支持。下面,通过一个简单的示例来演示如何在 Dubbo 中使用 gRPC 协议通信,详情参考:
https://github.com/apache/dubbo-samples/tree/master/dubbo-samples-grpc

  1. 定义服务 IDL

首先,通过标准的 Protobuf 协议定义服务如下:
syntax = “proto3”;

option java_multiple_files = true;
option java_package = “io.grpc.examples.helloworld”;
option java_outer_classname = “HelloWorldProto”;
option objc_class_prefix = “HLW”;

package helloworld;

// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user’s name.
message HelloRequest {
string name = 1;
}

// The response message containing the greetings
message HelloReply {
string message = 1;
}

在此,我们定义了一个只有一个方法 sayHello 的 Greeter 服务,同时定义了方法的入参和出参,

  1. Protobuf Compiler 生成 Stub

定义 Maven Protobuf Compiler 插件工具。这里我们扩展了 Protobuf 的 Compiler 工具,以用来生成 Dubbo 特有的 RPC stub,此当前以 Maven 插件的形式发布。

org.xolstice.maven.plugins
protobuf-maven-plugin
0.5.1

com.google.protobuf:protoc:3.7.1:exe: o s . d e t e c t e d . c l a s s i f i e r < / p r o t o c A r t i f a c t > < p l u g i n I d > d u b b o − g r p c − j a v a < / p l u g i n I d > < p l u g i n A r t i f a c t > o r g . a p a c h e . d u b b o : p r

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值