How des gRPC Work
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 服务器)的完整流程。 整个过程可以分解成以下几个步骤:
客户端发起请求:
- 客户端应用向订单服务发送一个 REST 请求。请求体通常是 JSON 格式 (例如:
{"productName": "keyboard", "quantity": "1", "price": "100"}
)。
订单服务(gRPC 客户端)处理请求:
- 订单服务接收 REST 请求。
- 订单服务将 REST 请求转换成 gRPC 请求。 这包括将 JSON 数据转换成 Protobuf 二进制格式。 图中的表格展示了 JSON 数据如何编码成 Protobuf 格式。 例如,字符串 “keyboard” 被编码成
6B 65 79 62 6F 61 72 64
。 - 订单服务通过 gRPC 运行时将 Protobuf 编码后的请求发送到传输层。
网络传输:
- gRPC 使用 HTTP/2 协议将数据包通过网络传输到支付服务。 由于使用了二进制编码和 HTTP/2 的网络优化,gRPC 的传输效率通常比 JSON 格式的 REST API 更高。
支付服务(gRPC 服务器)处理请求:
- 支付服务接收来自网络的数据包。
- 支付服务解码 Protobuf 数据包,将其转换回可理解的数据结构。
- 支付服务调用服务器应用的对应方法来处理请求。
支付服务返回响应:
- 服务器应用处理完成后返回结果。
- 支付服务将结果编码成 Protobuf 二进制格式。
- 支付服务将编码后的响应发送到传输层。
订单服务处理响应:
- 订单服务接收来自支付服务的响应数据包。
- 订单服务解码 Protobuf 数据包,将其转换回可理解的数据结构。
- 订单服务将结果返回给客户端应用。
总结:
这个流程展示了 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 是一个更好的选择。
开始实践
实践性文章在这里。