How des gRPC Work

img

Step 1: A REST call is made from the client. The request body is usually in JSON format.

Steps 2 - 4: The order service (gRPC client) receives the REST call, transforms it, and makes an RPC call to the payment service. gRPC encodes the client stub into a binary format and sends it to the low-level transport layer.

Step 5: gRPC sends the packets over the network via HTTP2. Because of binary encoding and network optimizations, gRPC is said to be 5X faster than JSON.

Steps 6 - 8: The payment service (gRPC server) receives the packets from the network, decodes them, and invokes the server application.

Steps 9 - 11: The result is returned from the server application, and gets encoded and sent to the transport layer.

Steps 12 - 14: The order service receives the packets, decodes them, and sends the result to the client application.

一个客户端应用通过订单服务(充当 gRPC 客户端)调用支付服务(充当 gRPC 服务器)的完整流程。 整个过程可以分解成以下几个步骤:

客户端发起请求:

  1. 客户端应用向订单服务发送一个 REST 请求。请求体通常是 JSON 格式 (例如:{"productName": "keyboard", "quantity": "1", "price": "100"})。

订单服务(gRPC 客户端)处理请求:

  1. 订单服务接收 REST 请求。
  2. 订单服务将 REST 请求转换成 gRPC 请求。 这包括将 JSON 数据转换成 Protobuf 二进制格式。 图中的表格展示了 JSON 数据如何编码成 Protobuf 格式。 例如,字符串 “keyboard” 被编码成 6B 65 79 62 6F 61 72 64
  3. 订单服务通过 gRPC 运行时将 Protobuf 编码后的请求发送到传输层。

网络传输:

  1. gRPC 使用 HTTP/2 协议将数据包通过网络传输到支付服务。 由于使用了二进制编码和 HTTP/2 的网络优化,gRPC 的传输效率通常比 JSON 格式的 REST API 更高。

支付服务(gRPC 服务器)处理请求:

  1. 支付服务接收来自网络的数据包。
  2. 支付服务解码 Protobuf 数据包,将其转换回可理解的数据结构。
  3. 支付服务调用服务器应用的对应方法来处理请求。

支付服务返回响应:

  1. 服务器应用处理完成后返回结果。
  2. 支付服务将结果编码成 Protobuf 二进制格式。
  3. 支付服务将编码后的响应发送到传输层。

订单服务处理响应:

  1. 订单服务接收来自支付服务的响应数据包。
  2. 订单服务解码 Protobuf 数据包,将其转换回可理解的数据结构。
  3. 订单服务将结果返回给客户端应用。

总结:

这个流程展示了 gRPC 如何通过 Protobuf 进行高效的序列化和反序列化,以及如何利用 HTTP/2 进行网络传输。 相比传统的 REST API,gRPC 通常具有更高的性能和更低的延迟。 此外,gRPC 的强类型定义也使得服务间的接口更加清晰和易于维护。

Why gRPC be created?

为了解决现代分布式系统中的一些挑战,其背景和原因可以总结如下:

背景:

  • 微服务架构的兴起: 随着微服务架构的流行,系统被拆分成许多小型服务,这些服务之间需要进行频繁的通信。传统的 RESTful API 在处理大量服务间通信时,效率和性能方面存在瓶颈。
  • 多语言环境: 现代应用通常使用多种编程语言开发。 需要一种跨语言的通信机制,以方便不同语言编写的服务之间进行交互。
  • 对高性能的需求: 随着实时应用和数据密集型应用的增长,对服务间通信的性能要求越来越高。

原因:

  • RESTful API 的局限性: RESTful API 通常使用 JSON 或 XML 进行数据交换,这些格式的解析和序列化效率相对较低。 此外,RESTful API 缺乏强类型的接口定义,容易出现兼容性问题。
  • HTTP/2 的优势: HTTP/2 协议的出现为构建高性能的 RPC 框架提供了基础。HTTP/2 支持双向流、多路复用和头部压缩等特性,可以显著提高通信效率。
  • 内部需求: Google 内部长期使用一个名为 Stubby 的 RPC 框架。gRPC 的开发最初是为了替代 Stubby,并将其开源,以造福更广泛的开发者社区。1

gRPC 的优势:

  • 高性能: gRPC 使用 Protobuf 进行二进制序列化,比 JSON 或 XML 更高效。结合 HTTP/2 的特性,gRPC 可以实现更高的吞吐量和更低的延迟。3
  • 强类型接口: gRPC 使用 Protobuf 定义服务接口,可以生成多种语言的客户端和服务器端代码。这使得接口更加清晰,减少了出错的可能性,并提高了开发效率。5
  • 跨语言支持: gRPC 支持多种编程语言,方便不同语言编写的服务之间进行交互。1
  • 流式传输: gRPC 支持客户端、服务器端和双向流式传输,可以更好地处理实时数据流。3
  • 内置安全机制: gRPC 支持多种身份验证和授权机制,可以保障服务间的安全通信。

总而言之,gRPC 的发明是为了解决现代分布式系统中对高性能、跨语言支持和强类型接口的需求,并充分利用了 HTTP/2 协议的优势。 它为构建微服务架构和云原生应用提供了一种高效的通信方案。

Advantages of gRPC over REST

gRPC 相较于 RESTful API 的优势,并从协议和实现原理的角度进行分析:

协议差异:

  • HTTP/1.1 vs. HTTP/2: RESTful API 通常基于 HTTP/1.1,而 gRPC 使用 HTTP/2。 这是 gRPC 性能优势的关键所在。HTTP/1.1 是一个文本协议,每个请求都需要建立一个新的 TCP 连接,并且请求之间是串行执行的。而 HTTP/2 是一个二进制协议,支持多路复用,允许多个请求在同一个 TCP 连接上并发执行,从而减少了连接建立的开销和延迟。 此外,HTTP/2 还支持头部压缩,进一步减少了数据传输量。
  • 文本 vs. 二进制: RESTful API 通常使用 JSON 或 XML 等文本格式进行数据交换,而 gRPC 使用 Protobuf 二进制格式。二进制格式的序列化和反序列化效率更高,数据量更小,从而提高了传输效率。

HTTP/1.1 vs. HTTP/2

使用命令获得进行两种协议的请求:

CheverJohn :: ~ % curl --http1.1 -I https://www.cloudflare.com/
CheverJohn :: ~ % curl --http2 -I https://www.cloudflare.com/
连接管理

虽然两个请求都使用了持久连接(Connection: keep-alive 在 HTTP/1.1 中出现),但它们的实现方式不同:

  • HTTP/1.1: 即使使用持久连接,同一连接上的请求仍然是串行处理的。 这意味着如果一个请求阻塞,后续的请求也必须等待。 这就是所谓的“队头阻塞”问题。
  • HTTP/2: 支持多路复用,允许多个请求和响应在同一连接上并发传输,避免了队头阻塞。 这意味着即使一个请求较慢,也不会影响其他请求的处理速度。
数据格式
  • HTTP/1.1: 使用明文传输头部和消息体,可读性强,但解析效率较低,也更容易受到攻击。
  • HTTP/2: 使用二进制帧传输数据,解析效率高,安全性也更高,但可读性差,需要专门的工具进行分析。
头部压缩
  • HTTP/1.1: 头部信息通常冗余且重复,增加了网络传输的开销。
  • HTTP/2: 使用 HPACK 算法压缩头部信息,减少了数据传输量,提高了效率。 你无法直接从 curl 的输出中看到这一点,需要使用网络抓包工具才能观察到。
服务器推送 (Server Push):
  • HTTP/1.1: 不支持服务器推送。 客户端需要显式地请求每个资源。
  • HTTP/2: 支持服务器推送。 服务器可以主动向客户端推送它认为客户端可能需要的资源,例如 CSS、JavaScript 文件等,从而减少了客户端的请求次数和延迟。 你提供的例子中没有体现这一点,因为服务器没有推送任何额外的资源。

gRPC 实现原理带来的优势:

  • Protobuf: gRPC 使用 Protobuf 作为接口定义语言 (IDL) 和消息格式。Protobuf 编译器可以生成多种语言的代码,这些代码包含了序列化、反序列化和网络通信的逻辑。这简化了开发流程,并确保了不同语言之间的数据交换一致性。
  • Stub: gRPC 使用 Stub 机制简化了客户端和服务器端的开发。客户端 Stub 提供了与服务器端相同的方法接口,客户端可以直接调用这些方法,就像调用本地方法一样。Stub 负责将请求参数序列化成 Protobuf 消息,并通过网络发送到服务器端。服务器端 Stub 负责接收请求,反序列化消息,调用服务器端的方法,并将结果序列化后返回给客户端。
  • 流式传输: gRPC 支持客户端流、服务器端流和双向流。这使得 gRPC 可以高效地处理实时数据流和大型数据集,而 RESTful API 通常只支持简单的请求-响应模式。

网络栈角度的分析:

从网络栈的角度来看,gRPC 的优势体现在以下几个方面:

  • 更少的 TCP 连接: HTTP/2 的多路复用特性减少了 TCP 连接的建立和维护开销,从而提高了网络利用率。
  • 更小的数据包: Protobuf 二进制格式的数据量更小,减少了网络传输时间。
  • 更低的延迟: HTTP/2 的多路复用和头部压缩,以及 Protobuf 的高效序列化,都降低了通信延迟。

总结:

gRPC 通过使用 HTTP/2 和 Protobuf,以及 Stub 机制和流式传输等特性,在性能、效率和易用性方面都优于传统的 RESTful API。 对于需要高性能、低延迟和跨语言支持的分布式系统来说,gRPC 是一个更好的选择。

开始实践

实践性文章在这里