gRPC
到目前为止,我们一直关注基于 REST 的通信。 我们已了解 REST 是一种灵活的体系结构样式,定义针对实体资源的基于 CRUD 的操作。 客户端使用请求/响应通信模型通过 HTTP 与资源进行交互。 虽然 REST 已广泛实现,但在云原生社区中,较新的通信技术 gRPC 也在蓬勃发展。
什么是 gRPC?
gRPC 是一种新式的高性能框架,它发展了由来已久的远程过程调用协议。 从应用程序层面来看,gRPC 简化了客户端和后端服务之间的消息传递。 gRPC 源自 Google,是云原生产品服务的云原生计算基础 (CNCF) 生态系统的一部分,并且是开放源代码的。 CNCF 将 gRPC 视为培育中的项目。 培育意味着最终用户会在生产应用程序中使用该技术,该项目有大量的贡献者。
典型的 gRPC 客户端应用将公开实现业务操作的本地进程内函数。 在此之下,该本地函数会在远程计算机上调用另一个函数。 看起来是本地调用,实际上变成了对远程服务的透明进程外调用。 RPC 管道对计算机之间点到点网络通信、序列化和执行进行抽象化。
在云原生应用程序中,开发人员在工作中通常会处理不同的编程语言、框架和技术。 这种互操作性使消息协定和跨平台通信所需的管道变得复杂。 gRPC 提供“统一水平层”来对此类问题进行抽象化。 开发人员在本机平台中编写专注于业务功能的代码,而 gRPC 会处理通信管道。
gRPC 在最常用的开发堆栈(包括 Java、JavaScript、C#、Go、Swift 和 NodeJS)中提供全面的支持。
gRPC 的优势
gRPC 使用 HTTP/2 作为传输协议。 虽然与 HTTP 1.1 也能兼容,但 HTTP/2 具有许多高级功能:
- 用于数据传输的二进制组帧协议 - 与 HTTP 1.1 不同,HTTP 1.1 是基于文本的。
- 对通过同一连接发送多个并行请求的多路复用支持 - HTTP 1.1 将处理限制为一次处理一个请求/响应消息。
- 双向全双工通信,用于同时发送客户端请求和服务器响应。
- 内置流式处理,支持对大型数据集进行异步流式处理的请求和响应。
- 减少网络使用率的标头压缩。
gRPC 是轻量型且高性能的。 其处理速度可以比 JSON 序列化快 8 倍,消息小 60% 到 80%。 在 Microsoft Windows Communication Foundation (WCF) 中,gRPC 的性能超过经过高度优化的 NetTCP 绑定的速度和效率。 与偏向于 Microsoft 堆栈的 NetTCP 不同,gRPC 是跨平台的。
协议缓冲区
gRPC 采用名为协议缓冲区的开放源代码技术。 它们提供极为高效且不受平台影响的序列化格式,用于序列化服务相互发送的结构化消息。 开发人员使用跨平台接口定义语言 (IDL) 为每个微服务定义服务协定。 该协定作为基于文本的 .proto
文件实现,描述了每个服务的方法、输入和输出。 同一合同文件可用于基于不同开发平台构建的 gRPC 客户端和服务。
Protobuf 编译器 protoc
使用 proto 文件为目标平台生成客户端和服务代码。 该代码包括以下组成部分:
- 由客户端和服务共享的强类型对象,表示消息的服务操作和数据元素。
- 一个强类型基类,具有远程 gRPC 服务可以继承和扩展的所需网络管道。
- 一个客户端存根,其中包含调用远程 gRPC 服务所需的管道。
运行时,每条消息都序列化为标准 Protobuf 表示形式,并在客户端和远程服务之间交换。 与 JSON 或 XML 不同,Protobuf 消息被序列化为经过编译的二进制字节。
.NET 中的 gRPC 支持
gRPC 集成到 .NET Core 3.0 SDK 及更高版本中。 以下工具对其提供支持:
- 已安装 ASP.NET 和 Web 开发工作负载的 Visual Studio 2022
- Visual Studio Code
dotnet
CLI
SDK 包括用于终结点路由、内置 IoC 和日志记录的工具。 开源 Kestrel Web 服务器支持 HTTP/2 连接。 图 4-20 展示 Visual Studio 2022 模板,该模板为 gRPC 服务搭建主干项目。 请注意 .NET 对 Windows Linux 和 macOS 提供完全支持的方式。
图 4-20。 Visual Studio 2022 中的 gRPC 支持
图 4-21 展示由 Visual Studio 2022 中包含的内置基架生成的 gRPC 服务框架。
图 4-21 。 Visual Studio 2022 中的 gRPC 项目
在上图中,请注意 proto 说明文件和服务代码。 正如你很快就会看到的,Visual Studio 会在 Startup 类和基础项目文件中生成其他配置。
gRPC 的使用
建议在以下场景中使用 gRPC:
- 需要立即响应才能继续处理的同步后端微服务到微服务通信。
- 需要支持混合编程平台的 Polyglot 环境。
- 性能至关重要的低延迟和高吞吐量通信。
- 点到点实时通信 - gRPC 无需轮询即可实时推送消息,并且能对双向流式处理提供出色的支持。
- 网络受约束环境 - 二进制 gRPC 消息始终小于等效的基于文本的 JSON 消息。
在撰写本文时,gRPC 主要用于后端服务。 新式浏览器无法提供支持前端 gRPC 客户端所需的 HTTP/2 控制级别。 也就是说,支持使用 .NET 的 gRPC-Web,能够从使用 JavaScript 或 Blazor WebAssembly 技术构建的基于浏览器的应用进行 gRPC 通信。 gRPC-Web 使 ASP.NET Core gRPC 应用能支持浏览器应用中的 gRPC 功能:
- 强类型、代码生成的客户端
- 压缩 Protobuf 消息
- 服务器流式处理
gRPC 实现
Microsoft 的微服务参考体系结构 eShop on Containers 介绍如何在 .NET 应用程序中实现 gRPC 服务。 图 4-22 展示的是后端体系结构。
图 4-22。 eShop on Containers 的后端体系结构
在上图中,请注意 eShop 如何通过公开多个 API 网关来采用前端模式的后端 (BFF)。 我们在本章中的前面部分讨论了 BFF 模式。 请密切关注聚合器微服务(灰色部分),它位于 Web-Shopping API 网关和后端购物微服务之间。 聚合器从客户端接收单个请求,将其调度到各种微服务、聚合结果并将其发送回请求的客户端。 此类操作通常需要同步通信,以生成即时响应。 在 eShop 中,聚合器中的后端调用使用 gRPC 执行,如图 4-23 所示。
图 4-23 。 eShop on Containers 中的 gRPC
gRPC 通信需要使用客户端和服务器组件。 在上图中,请注意购物聚合器是如何实现 gRPC 客户端的。 客户端对后端微服务进行同步 gRPC 调用(红色部分),每个调用都实现了一个 gRPC 服务器。 客户端和服务器都利用 .NET SDK 中的内置 gRPC 管道。 客户端存根提供用于发起远程 gRPC 调用的管道。 服务器端组件提供自定义服务类可以继承和使用的 gRPC 管道。
同时公开 RESTful API 和 gRPC 通信的微服务需要使用多个终结点来管理流量。 你将打开一个用于侦听 RESTful 调用的 HTTP 流量的终结点,并打开另一个侦听 gRPC 调用的终结点。 必须为 gRPC 通信所需的 HTTP/2 协议配置 gRPC 终结点。
尽管我们正在努力地将微服务与异步通信模式分离,但某些操作依然需要进行直接调用。 gRPC 应该是微服务之间直接同步通信的主要选择。 基于 HTTP/2 和协议缓冲区的高性能通信协议使其成为最佳选择。
展望未来
在将来,gRPC 将获得云原生系统方面的关注。 性能优势以及开发方面的轻松度都是它的闪光点。 但是,REST 可能会存在很长时间。 它在公开 API 和后向兼容性方面具有很大优势。