gRPC 详细入门教程(一)核心概念、架构与生命周期
gRPC是现代开源高性能远程过程调用(RPC)框架,支持多种语言和跨环境通信。文章系统介绍了gRPC的核心概念、应用场景和优势:1) 采用协议缓冲区定义服务接口,支持四种通信模式;2) 基于HTTP/2协议,提供双向流式传输;3) 具有负载均衡、健康检查等可插拔功能。内容涵盖入门指南、架构设计、RPC生命周期及常见问题,特别适合构建低延迟、高扩展性的分布式系统。gRPC源自Google内部技术,现
系列文章目录
目录
3.17 能否使用我偏好的数据格式(JSON、Protobuf、Thrift、XML)配合gRPC?
3.20 为何 gRPC 优于 HTTP/2 传输的二进制数据块?
前言
gRPC 是一个现代开源的高性能远程过程调用(RPC)框架,可在任何环境中运行。它能高效连接数据中心内及跨数据中心的服务,并支持可插拔的负载均衡、追踪、健康检查和身份验证功能。它同样适用于分布式计算的最后一公里,将设备、移动应用和浏览器连接至后端服务。
0.1 主要应用场景
- 高效连接微服务架构中的多语言服务
- 连接移动设备、浏览器客户端与后端服务
- 生成高效客户端库
0.2 核心优势特性
- 支持11种语言的原生客户端库
- 高效传输与简洁的服务定义框架
- 基于HTTP/2传输的双向流式传输
- 可插拔认证、追踪、负载均衡与健康检查
0.3 谁在使用gRPC?为何选择它?
众多企业已将gRPC用于连接环境中的多项服务。应用场景涵盖本地或云端环境中,从连接少量服务到数百项跨语言服务的各种需求。以下是部分早期采用者的详细案例与评价。
0.4 gRPC背后的故事
gRPC最初由谷歌创建。十多年来,谷歌一直使用名为Stubby的通用RPC基础设施,连接其数据中心内部及跨数据中心运行的海量微服务。2015年3月,谷歌决定开发Stubby的下一代版本并将其开源。由此诞生的gRPC如今已被谷歌以外的众多组织采用,广泛应用于从微服务到计算“最后一公里”(移动端、网页及物联网)的各类场景。
一、gRPC 入门指南
gRPC 与协议缓冲区入门指南
本页面将向您介绍gRPC和协议缓冲区。gRPC既可将协议缓冲区用作接口定义语言(IDL),也可将其作为底层消息交换格式。如果您初次接触gRPC和/或协议缓冲区,请务必阅读本文!若您只想直接动手实践,先了解gRPC的实际应用,请选择一种语言并尝试其快速入门指南。
1.1 概述
在 gRPC 中,客户端应用程序可以直接调用不同机器上服务器应用程序的方法,如同调用本地对象一般,这使得创建分布式应用程序和服务变得更加容易。与许多 RPC 系统类似,gRPC 基于定义服务的核心理念,通过指定可远程调用的方法及其参数和返回类型来实现。在服务器端,服务器实现该接口并运行 gRPC 服务器来处理客户端调用。在客户端,客户端拥有一个存根(某些语言中仅称为客户端),该存根提供与服务器相同的方法。

gRPC客户端和服务器可在多种环境中运行并相互通信——从谷歌内部服务器到您自己的桌面设备——且可使用gRPC支持的任意语言编写。例如,您可轻松创建Java语言的gRPC服务器,同时支持Go、Python或Ruby语言的客户端。此外,最新谷歌API将提供gRPC接口版本,让您能便捷地将谷歌功能集成到应用程序中。
1.2 协议缓冲区使用指南
默认情况下,gRPC采用谷歌成熟的开源结构化数据序列化机制——协议缓冲区(虽也可兼容JSON等其他数据格式)。以下简要介绍其工作原理。若您已熟悉协议缓冲区,可直接跳至下一节。
使用协议缓冲区的第一步是在 proto 文件中定义待序列化数据的结构:这是一种带有 .proto 扩展名的普通文本文件。协议缓冲区数据以消息形式组织,每条消息都是包含一系列名为字段的名称-值对的小型逻辑信息记录。以下是一个简单示例:
message Person {
string name = 1;
int32 id = 2;
bool has_ponycopter = 3;
}
然后,在指定数据结构后,您可使用协议缓冲编译器 protoc 从 proto 定义生成目标语言的数据访问类。这些类为每个字段提供简易访问器(如 name() 和 set_name()),并提供将整个结构序列化为原始字节或从原始字节反序列化的方法。例如,若您选择 C++ 作为目标语言,对上述示例运行编译器将生成名为 Person 的类。您可在应用程序中使用该类来填充、序列化及检索 Person 协议缓冲区消息。
您可在普通 proto 文件中定义 gRPC 服务,其中 RPC 方法的参数和返回类型均以协议缓冲区消息的形式指定:
// The greeter service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
gRPC通过protoc配合专用的gRPC插件,可从您的proto文件生成代码:您将获得生成的gRPC客户端和服务器代码,以及用于填充、序列化和检索消息类型的常规协议缓冲区代码。若需深入了解协议缓冲区(包括如何在您选择的语言中安装带gRPC插件的protoc),请参阅协议缓冲区文档。
1.3 协议缓冲区版本
虽然协议缓冲区已向开源用户开放多年,但本站多数示例采用协议缓冲区第 3 版(proto3),其语法略有简化,新增若干实用功能,并支持更多编程语言。目前协议缓冲区 GitHub 仓库提供 proto3 的 Java、C++、Dart、Python、Objective-C、C#、轻量级运行时(Android Java)、Ruby 和 JavaScript 版本,同时 golang/protobuf 官方包提供 Go 语言生成器,更多语言版本正在开发中。您可查阅 proto3 语言指南及各语言的参考文档获取详细信息。参考文档还包含.proto文件格式的正式规范。
总体而言,虽然您仍可使用Proto2(当前默认协议缓冲版本),但我们建议您在gRPC中采用Proto3。这不仅能支持gRPC全系列语言,更能避免Proto2客户端与Proto3服务器互通时的兼容性问题。
二、核心概念、架构与生命周期
gRPC核心概念入门指南,涵盖gRPC架构概述与RPC生命周期解析。
不熟悉 gRPC?请先阅读《gRPC 入门指南》。如需了解特定语言的详细信息,请查阅您所选语言的快速入门指南、教程和参考文档。
2.1 概述
2.1.1 服务定义
与许多RPC系统类似,gRPC的核心理念是定义服务,指定可远程调用的方法及其参数和返回类型。默认情况下,gRPC采用协议缓冲区作为接口定义语言(IDL),用于描述服务接口和有效负载消息的结构。若需使用其他替代方案,亦可实现。
service HelloService {
rpc SayHello (HelloRequest) returns (HelloResponse);
}
message HelloRequest {
string greeting = 1;
}
message HelloResponse {
string reply = 1;
}
gRPC 允许您定义四种服务方法:
- 一元 RPC:客户端向服务器发送单个请求并获取单个响应,就像普通函数调用一样。
rpc SayHello(HelloRequest) returns (HelloResponse); - 服务器流式RPC中,客户端向服务器发送请求后会获得一个流,用于读取返回的消息序列。客户端从返回的流中读取消息,直至消息耗尽。gRPC保证单次RPC调用内消息的顺序性。
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse); - 客户端流式RPC中,客户端会写入一系列消息并通过提供的流将其发送至服务器。完成消息写入后,客户端将等待服务器读取消息并返回响应。同样地,gRPC保证了单次RPC调用内消息的顺序性。
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse); - 双向流式RPC中,双方均通过读写流发送消息序列。两个流独立运行,因此客户端和服务器可按任意顺序读写:例如服务器可等待接收所有客户端消息后再写入响应,也可交替读取一条消息后写入一条消息,或采用其他读写组合方式。每个流中的消息顺序均得到保留。
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);
您将在下文的RPC生命周期章节中深入了解不同类型的RPC。
2.1.2 使用API
基于.proto文件中的服务定义,gRPC提供协议缓冲编译器插件来生成客户端和服务器端代码。gRPC用户通常在客户端调用这些API,并在服务器端实现对应的API。
- 在服务器端,服务器实现服务声明的方法,并运行 gRPC 服务器处理客户端调用。gRPC 基础设施负责解码传入请求、执行服务方法以及编码服务响应。
- 客户端拥有名为存根(stub)的本地对象(某些语言更倾向使用客户端一词),该对象实现与服务相同的方法。客户端只需调用本地对象的方法,这些方法会将调用参数封装为相应的协议缓冲区消息类型,将请求发送至服务器,并返回服务器的协议缓冲区响应。
2.1.3 同步与异步
同步RPC调用会阻塞直至收到服务器响应,这种特性最接近RPC所追求的程序调用抽象。另一方面,网络本质上是异步的,在许多场景中,能够在不阻塞当前线程的情况下启动RPC调用非常实用。
大多数语言的 gRPC 编程 API 同时提供同步与异步两种模式。更多详情请参阅各语言的教程和参考文档(完整参考文档即将发布)。
2.2 RPC生命周期
本节将深入解析gRPC客户端调用服务器方法时的运行机制。完整实现细节请参阅各语言专属文档。
2.2.1 一元RPC
首先考虑最简单的RPC类型:客户端发送单个请求并获取单个响应。
- 当客户端调用存根方法时,服务器会收到RPC调用通知,其中包含本次调用的客户端元数据、方法名称及(如有)指定的截止时间。
- 此时服务器可立即返回自身的初始元数据(必须在任何响应前发送),或等待客户端的请求消息。两者何者优先取决于具体应用场景。
- 服务器收到客户端请求消息后,执行必要操作生成响应内容。若操作成功,则将响应结果连同状态详情(状态码及可选状态消息)和可选尾随元数据一并返回给客户端。
- 若响应状态为OK,客户端接收响应后即完成客户端侧调用。
2.2.2 服务器流式RPC
服务器流式RPC类似于单向RPC,区别在于服务器会针对客户端请求返回消息流。发送完所有消息后,服务器的状态详情(状态码和可选状态消息)以及可选尾部元数据将发送至客户端。至此服务器端处理完成。当客户端接收完所有服务器消息后即完成处理。
2.2.3 客户端流式RPC
客户端流式RPC类似于单向RPC,区别在于客户端向服务器发送的是消息流而非单条消息。服务器通常(但非必须)在接收完所有客户端消息后,以单条消息(附带状态详情及可选尾部元数据)进行响应。
2.2.4 双向流式RPC
在双向流式RPC中,调用由客户端发起方法调用,服务器接收客户端元数据、方法名及截止时间。服务器可选择立即发送初始元数据,或等待客户端开始流式传输消息。
客户端与服务端的流处理逻辑因应用而异。由于两个流相互独立,客户端和服务器可按任意顺序读写消息。例如:服务器可等待接收完所有客户端消息后再写入自身消息;或采用“乒乓模式”——服务器接收请求后立即发送响应,客户端再根据响应发送新请求,如此循环往复。
2.2.5 截止时间/超时机制
gRPC允许客户端指定愿意等待RPC完成的时间长度,超过该时限后RPC将因DEADLINE_EXCEEDED错误终止。在服务器端,可查询特定RPC是否已超时,或剩余完成RPC的时间。
指定截止时间或超时机制因语言而异:某些语言的 API 以超时(时间长度)为单位工作,而另一些语言的 API 则以截止时间(固定时间点)为单位工作,且可能具有默认截止时间,也可能没有。
2.2.6 RPC 终止
在 gRPC 中,客户端和服务器会独立且本地地判断调用是否成功,且两者的结论可能不一致。这意味着,例如某个 RPC 在服务器端成功完成(“我已发送所有响应!”),但在客户端却失败(“响应在我的时限后到达!”)。服务器也可能在客户端发送完所有请求前就决定结束调用。
2.2.7 取消RPC调用
客户端或服务器均可随时取消RPC调用。取消操作将立即终止RPC进程,阻止后续工作继续执行。
警告
取消操作前所做的更改不会被撤销。
2.2.8 元数据
元数据是以键值对列表形式呈现的特定RPC调用信息(如身份验证详情),其中键为字符串,值通常为字符串,但也可能是二进制数据。
键不区分大小写,由ASCII字母、数字及特殊字符 -、_、. 组成,且不得以 grpc- 开头(该前缀为gRPC自身保留)。二进制键值以 -bin 结尾,ASCII 键值则不带后缀。
用户定义的元数据不被 gRPC 使用,它允许客户端向服务器提供与调用相关的信息,反之亦然。
元数据的访问方式取决于编程语言。
2.2.9 通道(Channel)
gRPC通道用于连接指定主机端口的gRPC服务器,在创建客户端存根时使用。客户端可通过通道参数修改gRPC默认行为(如启用/禁用消息压缩)。通道具有连接状态(connected)和空闲状态(idle)。
gRPC处理通道关闭的方式因语言而异。部分语言还支持查询通道状态。
三、常见问题解答
3.1 什么是 gRPC?
gRPC 是一个现代开源的远程过程调用(RPC)框架,可在任何环境中运行。它使客户端与服务器应用程序能够透明通信,并简化了互联系统的构建。
阅读更详尽的《动机与设计原则》文章,了解我们创建 gRPC 的背景。
3.2 gRPC 代表什么?
当然是 gRPC 远程过程调用(gRPC Remote Procedure Calls)!
3.3 为何选择使用 gRPC?
主要应用场景:
- 低延迟、高可扩展性的分布式系统。
- 开发与云服务器通信的移动客户端。
- 设计需兼具精准性、高效性与语言无关性的新型协议。
- 分层设计以支持扩展功能(如身份验证、负载均衡、日志记录与监控等)。
3.4 哪些用户在使用它?原因何在?
gRPC 是云原生计算基金会(CNCF)的项目。
Google 长期以来一直在使用 gRPC 中的许多底层技术和概念。当前的实现方案已被应用于多个 Google 云产品和面向外部的 Google API。此外,Square、Netflix、CoreOS、Docker、CockroachDB、Cisco、Juniper Networks 以及众多其他组织和个人也在使用 gRPC。
3.5 支持哪些编程语言?
官方支持的语言和平台请参阅官方支持文档。
3.6 如何开始使用 gRPC?
可通过此处指南安装 gRPC。或访问 gRPC GitHub 组织页面,选择所需运行时或语言,并遵循 README 说明操作。
3.7 gRPC 采用何种许可协议?
所有实现均采用 Apache 2.0 许可证。
3.8 如何参与贡献?
我们热忱欢迎贡献者加入,相关仓库托管于 GitHub。期待社区反馈、功能补充及问题报告。个人与企业贡献者均需签署我们的贡献者协议(CLA)。若您有围绕 gRPC 的项目构想,请阅读指南并在此提交。GitHub 上的 gRPC 生态系统组织下正持续扩展项目列表。
3.9 文档在哪里?
请访问 grpc.io 查阅文档。
3.10 路线图是什么?
gRPC 项目采用 RFC 流程设计并批准新功能的实现,相关进展在此仓库中跟踪。
3.11 gRPC版本支持周期有多长?
gRPC项目不提供长期支持(LTS)版本。基于上述滚动发布模式,我们仅支持当前最新版本及其前一版本,支持内容包括漏洞修复与安全更新。
3.12 gRPC版本管理政策是什么?
请参阅此处的gRPC版本管理政策。
3.13 最新 gRPC 版本是什么?
最新发布标签为 v1.74.0。
3.14 gRPC 发布周期如何安排?
gRPC 项目采用主分支尖端始终稳定的模式运行。项目(涵盖各类运行时)力求每 6 周发布一次检查点版本。发布计划详见此处。
3.15 如何报告 gRPC 中的安全漏洞?
请遵循此处记录的流程报告 gRPC 安全漏洞。
3.16 能否在浏览器中使用?
gRPC-Web 项目已全面可用。
3.17 能否使用我偏好的数据格式(JSON、Protobuf、Thrift、XML)配合gRPC?
可以。gRPC设计上具备可扩展性,支持多种内容类型。初始版本支持Protobuf,并通过外部支持实现对FlatBuffers、Thrift等其他内容类型的兼容(成熟度各异)。
3.18 能否在服务网格中使用 gRPC?
可以。gRPC 应用程序可像其他应用程序一样部署在服务网格中。gRPC 还支持 xDS API,这使得无需使用边车代理即可在服务网格中部署 gRPC 应用程序。gRPC 支持的无代理服务网格功能列表详见此处。
3.19 gRPC 如何助力移动应用开发?
gRPC 和 Protobuf 提供了一种便捷方式,可精确定义服务并自动生成适用于 iOS、Android 及后端服务器的可靠客户端库。客户端能利用先进的流式传输和连接特性,从而节省带宽、通过更少的 TCP 连接完成更多任务,并降低 CPU 占用和电池消耗。
3.20 为何 gRPC 优于 HTTP/2 传输的二进制数据块?
这主要源于 gRPC 的传输特性。但 gRPC 同时作为一组库,能提供跨平台一致的高级功能,这是普通 HTTP 库通常不具备的。例如:
- 应用层流量控制交互
- 级联式调用取消
- 负载均衡与故障转移
3.21 为何 gRPC 优于/逊于 REST?
gRPC 基本遵循 HTTP/2 的语义规范,但我们明确支持全双工流传输。其与典型 REST 规范的差异在于:为提升调用分派性能,我们采用静态路径机制——从路径、查询参数和负载主体解析调用参数会增加延迟与复杂度。我们还正式定义了一套错误代码体系,相较于HTTP状态码,我们认为其更直接适用于API使用场景。
3.22 如何发音gRPC?
发音为:吉-艾尔-皮-西。
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)