AB
AiBoss站
百科

什么是 gRPC(gRPC)?一种语言无关的高性能远程过程调用框架

gRPC 是一种语言无关、高性能的远程过程调用(RPC)框架。它采用契约优先的开发方式,默认使用 Protocol Buffers 定义服务与消息,并支持客户端、服务端与双向流式调用。本文依据 Microsoft Learn 的官方文档,介绍它的定义、出现背景、工作机制、典型用法与适用边界。

gRPC 是一种语言无关(language agnostic)、高性能的远程过程调用(Remote Procedure Call,RPC)框架。按照 Microsoft Learn 官方文档的说法,它让运行在不同机器、由不同语言编写的程序可以像调用本地方法一样互相调用,并以契约优先(contract-first)的方式把接口定义与实现分离。它主要解决的是:在微服务与多语言系统里,如何用一份明确的接口契约,生成强类型的服务端与客户端,并以较小的网络开销完成调用与流式传输。

为什么重要

在 gRPC 这类框架出现之前,跨进程、跨机器的调用通常依赖手写的 HTTP 接口封装,或者依赖与特定语言绑定的 RPC 实现。前者的问题在于接口契约往往散落在文档和代码里,客户端与服务端各自手写序列化与反序列化逻辑,字段一旦改动就容易出现不一致;后者的问题在于难以在多种语言之间共享同一套服务定义。

Microsoft Learn 的文档把 gRPC 的主要收益归纳为几点:它是现代、高性能、轻量的 RPC 框架;采用契约优先的 API 开发方式,默认使用 Protocol Buffers,从而支持语言无关的实现;为多种语言提供工具链,可生成强类型的服务端与客户端;支持客户端流、服务端流与双向流式调用;借助 Protobuf 二进制序列化减少网络用量。文档据此认为,gRPC 适合效率至关重要的轻量微服务、需要多种语言参与开发的多语言系统,以及需要处理流式请求或响应的点对点实时服务。

换句话说,gRPC 的价值不在于发明了远程调用这件事,而在于把「接口契约」「代码生成」「二进制序列化」「流式传输」组合成一套可跨语言复用的工程约定。

工作机制

按照 Microsoft Learn 文档的描述,gRPC 的核心做法可以拆成以下几个环节。

  • 契约优先定义接口。 服务与消息都写在 .proto 文件里。文档给出的示例使用 proto3 语法,声明一个 Greeter 服务,其中包含一个 SayHello 方法,接收 HelloRequest 并返回 HelloReply;两个消息类型各自带有一个字符串字段。
  • 由工具生成强类型代码。 在 .NET 项目中,把 .proto 文件加入项目的 Protobuf 项组,并引用 Grpc.Tools 包,工具就会自动生成服务、客户端与消息对应的 .NET 类型。文档强调,正是这一步让不同语言都能得到强类型的服务端与客户端。
  • 在服务端托管服务。 gRPC 服务可以托管在 ASP.NET Core 上,并与日志、依赖注入(Dependency Injection,DI)、身份认证与授权等框架特性集成。服务端需要引用 Grpc.AspNetCore 包;生成的 GreeterService 继承自根据 .proto 生成的 GreeterBase 类型,并在 Program.cs 中通过 app.MapGrpcService<GreeterService>() 暴露给客户端。
  • 客户端通过通道发起调用。 客户端类型同样由 .proto 文件生成,其方法与 .proto 中定义的服务方法一一对应。文档示例先用 GrpcChannel.ForAddress 创建一个通道,该通道代表到 gRPC 服务的长连接,再由通道构造出具体的客户端,然后调用 SayHelloAsync 并读取返回消息。
  • 以二进制格式传输。 消息默认使用 Protobuf 二进制序列化,相比文本格式可以减少网络用量,这也是文档所列「高性能、轻量」说法的来源之一。

此外,文档明确列出 gRPC 支持客户端流、服务端流与双向流式调用,这使得它不局限于「一问一答」式的请求响应模型。

典型例子

Microsoft Learn 文档给出的示例是一个问候服务,它同时覆盖了服务端与客户端两侧,是理解 gRPC 工作方式的最小完整例子。

契约部分定义在 .proto 文件中:Greeter 服务声明 SayHello 方法,输入为带 name 字段的 HelloRequest,输出为带 message 字段的 HelloReply。

服务端方面,ASP.NET Core 的 gRPC 服务项目模板提供一个起始服务:GreeterService 继承 Greeter.GreeterBase,重写 SayHello 方法,通过注入的日志记录器记录来访名称,并返回一条拼接了名称的问候消息。文档同时给出了使用主构造函数写法和传统构造函数写法的两个版本。

客户端方面,文档示例先创建到 https://localhost:5001 的通道,再构造 Greeter.GreeterClient,调用 SayHelloAsync 传入名称,最后把返回的消息打印出来。

文档还说明了这些收益对应的适用场景:效率至上的轻量微服务、需要多种语言开发的多语言系统,以及需要处理流式请求或响应的点对点实时服务。这些是文档作者的判断,属于该文档对 gRPC 适用面的表述,而非某种独立的行业结论。

边界与常见误解

第一,gRPC 不等于「任何场景都更优的 HTTP 替代品」。上述文档把它的优势放在高性能、轻量、多语言与流式这些维度上,并据此圈定了微服务、多语言系统和实时流式服务等适用场景;反过来,文档并没有主张它在所有接口形态下都优于其他方案。选型时仍要结合调用模式、客户端环境与团队工具链来判断。

第二,契约优先不等于「写完 .proto 就万事大吉」。文档描述的流程里,.proto 文件需要被纳入项目构建(例如加入 Protobuf 项组并引用 Grpc.Tools),代码才由工具生成;服务端还需要引用 Grpc.AspNetCore 并完成托管配置。也就是说,契约是起点,工具链与运行时配置同样是必要环节。

第三,不要把「语言无关」误解为「无需关心语言差异」。文档的表述是:借助 Protocol Buffers 与多语言工具链,可以生成强类型的服务端与客户端,从而实现语言无关的实现。实际使用中,各语言的工具支持程度、生成代码的风格与集成方式仍由各自的工具链决定,文档也把 C# 相关的工具支持单独成篇说明。

第四,关于性能的说法应回到出处。文档把「高性能、轻量」「减少网络用量」列为 gRPC 的主要收益,并归因于 Protobuf 二进制序列化等设计;这些是 Microsoft Learn 文档的表述,具体到某个系统的实际表现,取决于消息结构、网络条件与实现细节,文档本身并未给出通用的量化结论。

第五,流式能力有适用前提。文档列出客户端流、服务端流与双向流,并把它与「点对点实时服务」联系起来;但这并不意味着所有部署环境、所有代理与客户端都天然适合长连接流式通信,这类工程约束需要按具体环境评估。

参考资料