系列文章目录

目录

系列文章目录

前言

0.1 主要应用场景

0.2 核心优势特性

0.3 谁在使用gRPC?为何选择它?

0.4 gRPC背后的故事

一、gRPC 入门指南

1.1 概述

1.2 协议缓冲区使用指南

1.3 协议缓冲区版本

二、核心概念、架构与生命周期

2.1 概述

2.1.1 服务定义

2.1.2 使用API

2.1.3 同步与异步

2.2 RPC生命周期

2.2.1 一元RPC

2.2.2 服务器流式RPC

2.2.3 客户端流式RPC

2.2.4 双向流式RPC

2.2.5 截止时间/超时机制

2.2.6 RPC 终止

2.2.7 取消RPC调用

2.2.8 元数据

2.2.9 通道(Channel)

三、常见问题解答

3.1 什么是 gRPC?

3.2 gRPC 代表什么?

3.3 为何选择使用 gRPC?

3.4 哪些用户在使用它?原因何在?

3.5 支持哪些编程语言?

3.6 如何开始使用 gRPC?

3.7 gRPC 采用何种许可协议?

3.8 如何参与贡献?

3.9 文档在哪里?

3.10 路线图是什么?

3.11 gRPC版本支持周期有多长?

3.12 gRPC版本管理政策是什么?

3.13 最新 gRPC 版本是什么?

3.14 gRPC 发布周期如何安排?

3.15 如何报告 gRPC 中的安全漏洞?

3.16 能否在浏览器中使用?

3.17 能否使用我偏好的数据格式(JSON、Protobuf、Thrift、XML)配合gRPC?

3.18 能否在服务网格中使用 gRPC?

3.19 gRPC 如何助力移动应用开发?

3.20 为何 gRPC 优于 HTTP/2 传输的二进制数据块?

3.21 为何 gRPC 优于/逊于 REST?

3.22 如何发音gRPC?


前言

        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类型:客户端发送单个请求并获取单个响应。

  1. 当客户端调用存根方法时,服务器会收到RPC调用通知,其中包含本次调用的客户端元数据、方法名称及(如有)指定的截止时间。
  2. 此时服务器可立即返回自身的初始元数据(必须在任何响应前发送),或等待客户端的请求消息。两者何者优先取决于具体应用场景。
  3. 服务器收到客户端请求消息后,执行必要操作生成响应内容。若操作成功,则将响应结果连同状态详情(状态码及可选状态消息)和可选尾随元数据一并返回给客户端。
  4. 若响应状态为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?

        发音为:吉-艾尔-皮-西。

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐