A tour of gRPC:01 - 基础理论
gRPC 的动机
在实际工程中后端服务实现方式往往不止一种,并且由于技术或者业务的限制,通常会存在着多种语言 编写的服务。而服务间为了相互通讯就必须使用一种统一的 API 契约达成一种一致的协议。该协议要规 定诸如:通讯信道,身份验证机制、负载格式、数据模型和如何处理异常情况。
当然我们希望通讯可以做到高效(快速且轻量),由于微服务间服务信息交换的数量通常是巨大的,所以通信也理应越快越好。同时在例如移动应用或其他网速和带宽是有限的情景下,有一个轻量级的通信协议与后端服务进行交互非常重要。
最后,我们也希望通信尽可能的简单,例如我们现在一个拥有千个服务的系统,我们不想花大量的时间编写让服务相互通信的代码。我们想要的是某种框架,让框架来帮我们完成一切通信相关内容,让开发人员专注于实现服务的核心业务逻辑。
gRPC 是什么?
gRPC 最初由 google 所开发,所以 gRPC 中的 g 往往被认为代表 google 的意思,事实上在 gRPC 1.0 的时候确实是这样,不过后续版本的 g 相当于一个版本代号 (例如 1.1 的 g 代表 good),可以在 gRPC 版本代号 进行查看。而 gRPC 现在属于 云原生基金会(CNCF) 的一部分(如同 k8s)。那么 RPC 代表什 么呢?Remote Procedure Calls 它是一种调用的形式,通俗的说,它通过底层框架进行的自动处理,允 许一台计算机上的程序调用另一台计算机上的程序。这种调用在服务端看来,我们直接在客户端上调用 了一个服务端代码的方法(或函数)。
gRPC 是如何工作的?
client 拥有一个 stub (桩)它提供与 Server 相同的方法,stub 由 gRpc 自动生成。 Stub 在后台调用 gRPC 框架通过网络与 server 交换信息 。由于 stub 的存在,client 和 server 现在只需要关心实现业务 的核心逻辑 。
gRPC 代码生成
gRPC 是如何帮助我们生成 stub 的?
为了给 server 和 client 生成 stub 我们必须要先在 Protocol Buffer 文件中编写 API 合约(规则),包 括 服务的描述 和它的 有效消息载荷(payload)。
下面展示一个简单的 protoBuf 格式的 Protocol Buffer
在上的示例文件中,定义了 Hello 方法(函数),它以 HelloRequest 作为输入,并返回一个 HelloResponse ,其中 HelloRequest 仅包含一个字符串 name, HelloResponse 也有一个字符串 greet 。从类似这样的原始文件中,由协议缓冲区编译器根据编程语言,生成 server 和 client 的 stub 代码。
那么 gRPC 为什么使用了 protocol buffer 作为 API 规约?
1. 它非常容易阅读和理解
2. 让不同编程语言,拥有统一的一种描述
3. 使用二进制格式,同 JSON/XML 等基于文本的格式相比,更小、更易传输 和 更好的序列/反序列化性能
4. 提供了 client 和 server 间的 强类型(Strongly typed) API 合约
5. 拥有大量的 API 演化规则,保证了 API 的向前/向后 兼容
事实上 gRPC 并不与 Protocol Buffer 强绑定,我们可以使用 Google Flatbuffers 或 Microsoft Bond 代替 Protocol Buffer 。但是 Protocol Buffer 是一个棒的规则,因为它被多种编程语言所支持。
原生实现:GO、Java、NodeJS
包装实现:C/C++、C#、Objective-C、Python、Ruby、Dart、PHP
非官方支持的第三方库:swift rust typescript ....
gRPC 为什么高效
gRPC 使用 HTTP/2 作为其传输协议,因此,它继承了 HTTP/2 所提供的一些出色的功能 。例如 二进制 格式,与其他使用基于文本的协议相比,性能更高、更健壮、传输更轻便、解码更安全,与 protocol buffer 的结合也更好;同时 Http/2 还使用 HPACK 压缩 HEAD,减少开销并提高性能;Http/2 中还可以 进行多路复用,这意味着客户端和服务端可以通过单个 TPC 连接并行的发送多个请求和接收多个响应, 这能有效减少延迟以提高网络的利用效率;Http/2 还允许服务器进行推送,在客户端发出单个请求的情 况下,服务端可以返回多个响应,在多数情况下,这对减少 客户端 和 服务端 之间的往返延迟非常有价值。
Http/2 底层是怎么运行的
HTTP/2 一个 TCP 连接可承受多个双向流,每个流都有唯一的标识符并携带多个双向消息,每个消息 (请求/响应)都可以分解为多个二进制帧,帧是承载不同数据类型的最小单位,如:HEADERS(头)、SETTINGS(设置)、PRIORITY(优先级)、DATA(数据等)等。
不同流上的帧在连接上交错,并将在到达另一端时重新组装。
HTTP/2 vs HTTP/1.1
我们再看一眼 HTTP/2 与我们熟悉的 HTTP/1.1 的对比
gRPC 的四种类型
一元 unary:client 发送一个请求,server 回复一个响应
客户端流 client streaming:客户端发送多个消息流请求,期望 server 仅回复一个响应
服务器流 server streaming:客户端仅发送一个请求,服务端回复多个消息流响应
双向流 bidirectional streaming:客户端和服务器将平行发送多个请求和响应,它非常灵活并且是 非阻塞的,这意味着,任何一方都不需要在发送下一条消息之前等待响应。
gRPC vs REST
gRPC 的适用场景
微服务是 gRPC 真正发挥作用的地方,因为它可以实现低延迟和高吞吐的通信。由于许多编程语言提供 了开箱即用的代码生成,所以它也适用于多种语言环境。点对点通信也是使用 gRPC 的好地方因为它对双 向流提供了良好的支持。最后,因为它轻量的消息格式,对于网络受限的环境也是一个不错的选择。
版权声明: 本文为 InfoQ 作者【BUG侦探】的原创文章。
原文链接:【http://xie.infoq.cn/article/10f896901d7c118b0c89e1c9c】。文章转载请联系作者。
评论