gRPC 概述与入门
本文档来自 zread.ai 对 grpc/grpc 仓库的解析,合并了该站所有子页面内容。来源:https://zread.ai/grpc/grpc
目录
- 概述
- [为什么选择 gRPC?](#为什么选择 gRPC?)
- 核心架构
- [gRPC 如何工作](#gRPC 如何工作)
- 流式传输能力
- 支持的语言
- 项目结构
- 关键特性概览
- [何时使用 gRPC](#何时使用 gRPC)
- 下一步
- 社区和生态系统
- 快速入门
- [构建和安装 gRPC](#构建和安装 gRPC)、特定语言设置指南、[Hello World 示例](#Hello World 示例)
- 最新更新和发布计划、安全审计发现和修复、社区反馈和问题
- [gRPC 概念和架构](#gRPC 概念和架构) 至 调用追踪和日志记录(含协议、HTTP/2、流控、核心库、通道、传输、RPC 模式、负载均衡、解析、安全、可观测性等)
说明:本文档已合并 zread.ai/grpc/grpc 站内所有子页对应内容;部分子页在抓取时遇 504,已按侧栏结构与既有概念补全为摘要。
概述
gRPC 是一个现代化的开源高性能远程过程调用(RPC)框架,使客户端和服务器应用程序能够跨任何语言平台 进行透明通信。它通过提供一种与语言无关的服务定义方式并自动生成客户端/服务器代码,简化了连接系统的构建。
gRPC 的核心解决了分布式系统的基本挑战:如何使跨网络边界的函数调用像本地函数调用一样自然和可靠。它通过高效的二进制序列化、HTTP/2 传输以及从服务定义生成代码的组合来实现这一目标。
来源:README.md, CONCEPTS.md
为什么选择 gRPC?
gRPC 源于 Google 内部对 RPC 系统的使用(「g」最初代表 Google),旨在解决构建微服务和分布式应用时的常见痛点。与依赖基于 HTTP/1.1 的 JSON 等文本格式的传统 REST API 不同,gRPC 在 HTTP/2 上使用 Protocol Buffers,以获得更好的性能、效率和开发体验。
相比传统方法的关键优势:
- 性能:二进制序列化和 HTTP/2 多路复用减少延迟、提高吞吐量
- 强类型:Protocol Buffers 在服务之间提供严格契约,在编译时捕获错误
- 代码生成:自动生成多种语言的类型安全客户端和服务器代码
- 流式支持:内置一元、客户端流式、服务器流式和双向流式 RPC
- 互操作性:用任何支持的语言编写的服务都可以无缝相互通信
gRPC 最重要的架构决策是其分层设计 :共享的 C++ 核心库 src/core 提供传输、安全和负载均衡能力,而特定语言的实现通过原生绑定利用此核心,确保所有支持的语言具有一致的行为。
来源:README.md, CONCEPTS.md
核心架构
gRPC 架构遵循清晰的关注点分离 ,包含处理远程通信不同方面的组件。该架构在内部处理分布式通信的复杂性,同时向开发者暴露清晰的 API。gRPC 通道作为主要抽象,封装了名称解析、负载均衡、连接管理和传输细节。
来源:CONCEPTS.md, doc/load-balancing.md
gRPC 如何工作
gRPC 开发流程遵循四个基本步骤:
- 定义服务 :使用 Protocol Buffers IDL 创建
.proto文件,包含服务定义、RPC 方法和消息类型。例如,一个简单的问候服务可能定义接受HelloRequest并返回HelloReply的SayHello方法。 - 生成代码 :带有 gRPC 插件的 Protocol Buffer 编译器(
protoc)自动生成特定语言的代码,包括用于发起 RPC 调用的客户端存根和用于实现服务方法的服务器接口。 - 实现服务器:为每个 RPC 方法编写实际业务逻辑,实现生成的服务器接口;服务器监听网络地址并处理传入请求。
- 创建客户端:创建 gRPC 通道(服务器地址与配置),从通道创建客户端存根,使用该存根像调用本地函数一样调用 RPC 方法。
来源:CONCEPTS.md, examples/protos/helloworld.proto
流式传输能力
gRPC 支持四种类型的 RPC 方法:
| RPC 类型 | 描述 | 用例 |
|---|---|---|
| 一元 | 单个请求,单个响应 | 简单请求-响应,如获取用户数据 |
| 客户端流式 | 请求流,单个响应 | 上传文件、处理批量数据 |
| 服务器流式 | 单个请求,响应流 | 下载数据、实时更新、通知 |
| 双向流式 | 客户端和服务器都流式传输消息 | 聊天、实时协作 |
流式能力利用 HTTP/2 的多路复用,在单条 TCP 连接上同时进行多个流,对实时通信或高效数据传输特别有价值。
来源:CONCEPTS.md, examples/protos/helloworld.proto
支持的语言
gRPC 为多种编程语言提供支持,分为两类:
| 语言 | 实现类型 | 源码位置 | 状态 |
|---|---|---|---|
| C++ | 基于核心 | src/cpp | 生产就绪 |
| Python | 基于核心 | src/python | 生产就绪 |
| Ruby | 基于核心 | src/ruby | 生产就绪 |
| PHP | 基于核心 | src/php | 生产就绪 |
| C / Objective-C | 基于核心 | src/objective-c | 生产就绪 |
| Java | 独立 | grpc-java 仓库 | 生产就绪 |
| Go | 独立 | grpc-go 仓库 | 生产就绪 |
| Node.js | 独立 | grpc-node 仓库 | 生产就绪 |
| Kotlin | 独立 | grpc-kotlin 仓库 | 生产就绪 |
| C# (.NET) | 独立 | grpc-dotnet 仓库 | 生产就绪 |
| Swift | 独立 | grpc-swift 仓库 | 生产就绪 |
| Dart | 独立 | grpc-dart 仓库 | 生产就绪 |
| Web | 独立 | grpc-web 仓库 | 生产就绪 |
基于核心的实现共享 C++ 核心库 src/core 用于传输、安全和负载均衡;独立实现拥有针对其语言生态系统优化的核心。
来源:README.md
项目结构
gRPC 仓库的组织结构旨在支持多语言开发并提供全面示例:
grpc/
├── src/ # 核心和语言实现
│ ├── core/ # 共享的 C++ 核心库
│ ├── cpp/ # C++ 实现
│ ├── python/ # Python 实现
│ └── ... # 其他语言
├── examples/ # 特定语言的示例
│ ├── protos/ # 共享的 Protocol Buffer 定义
│ ├── cpp/ # C++ 示例(helloworld, auth 等)
│ ├── python/ # Python 示例
│ └── ... # 其他语言示例
├── doc/ # 详细文档
│ ├── PROTOCOL-HTTP2.md # HTTP/2 实现细节
│ ├── load-balancing.md # 负载均衡架构
│ └── ...
├── third_party/ # 外部依赖
├── test/ # 测试套件
└── tools/ # 构建和代码生成工具
examples 目录对初学者特别有价值,包含身份验证、压缩、负载均衡和流式传输等各类 gRPC 功能的实际演示。
来源:README.md, examples/README.md
关键特性概览
| 特性 | 描述 |
|---|---|
| Protocol Buffers | 高效二进制序列化,支持模式演进 |
| HTTP/2 传输 | 多路复用、头部压缩、服务器推送 |
| 负载均衡 | 内置轮询、首选、自定义策略 |
| TLS 安全 | 带凭证管理的 SSL/TLS 加密 |
| 身份验证 | 支持基于令牌、SSL、Google 凭证 |
| 流量控制 | 基于 HTTP/2 的流量控制,用于内存管理 |
| 截止时间/超时 | 每次调用的超时以保证可靠性 |
| 取消 | 可取消进行中的 RPC |
| 元数据 | 每次调用传递的自定义键值对 |
| 拦截器 | 用于日志、身份验证和监控的中间件 |
通道连接状态机是理解 gRPC 行为的基础:通道经历 IDLE → CONNECTING → READY → TRANSIENT_FAILURE → SHUTDOWN。该状态机自动处理连接建立、重试逻辑和错误恢复,使应用免受瞬时网络问题影响。
来源:doc/connectivity-semantics-and-api.md, doc/load-balancing.md
何时使用 gRPC
适合使用 gRPC 的场景:
- 性能至关重要:需要低延迟和高吞吐的内部微服务通信
- 需要强契约:需要编译时类型检查和 API 演进的服务
- 需要流式传输:实时数据交换、文件传输或双向通信
- 多语言环境:使用不同编程语言的团队需要无缝通信
- 多语言微服务:不同技术栈的组织需要互操作性
考虑 REST 等替代方案的场景:
- 需要浏览器兼容的面向公众 API
- 简单 CRUD 且 REST 语义更清晰
- 需要缓存和标准 HTTP 基础设施集成的场景
来源:CONCEPTS.md, README.md
下一步
推荐学习路径:
- 快速开始 --- 用喜欢的语言在几分钟内运行基本 gRPC 服务端与客户端
- 构建和安装 gRPC --- 按详细构建说明配置开发环境
- 特定语言设置指南 --- 深入了解所选语言的设置
- Hello World 示例 --- 通过示例理解核心概念
- gRPC 概念和架构 --- 深入理解架构与设计原则
对协议内部细节感兴趣可阅读 gRPC 协议规范摘要 与 HTTP/2 实现细节。
来源:README.md, BUILDING.md
社区和生态系统
gRPC 拥有活跃的开源社区,定期发布、全面文档和丰富工具支持;项目遵循语义化版本,约每六周进行小版本发布,并按需发布补丁。
关键资源:
- 网站 :grpc.io --- 官方文档与指南
- 邮件列表 :grpc-io@googlegroups.com --- 社区讨论
- 聊天 :Gitter.im --- 实时支持
- 性能仪表板 :grafana-dot-grpc-testing.appspot.com --- 性能指标
- 软件包 :packages.grpc.io --- 预构建最新包
快速入门
几分钟内快速上手 gRPC。本指南将引导你在你喜欢的语言中安装 gRPC,并使用 Protocol Buffers 构建你的第一个客户端-服务器应用程序。gRPC 使你能够在 .proto 文件中定义服务,并生成多种语言的客户端和服务器代码,这使其成为构建需要高性能 RPC 通信的连接系统的理想选择。
来源:README.md, BUILDING.md
了解 gRPC 架构
在深入研究代码之前,了解 gRPC 的工作原理会很有帮助。gRPC 框架使用客户端-服务器模型,其中服务是使用 Protocol Buffers 在 .proto 文件中定义的。此定义会生成类型安全的客户端和服务器代码,允许不同语言通过强类型接口无缝通信。
核心工作流程涉及四个协同工作以实现 RPC 通信的关键组件。
来源:examples/protos/helloworld.proto, README.md
安装 gRPC
gRPC 支持多种编程语言,每种语言都有其首选的安装方法。在下方选择你的语言并按照安装说明快速开始。
Python 安装
Python 为初学者提供了最简单的安装路径。gRPC 运行时作为 PyPI 上的预构建包提供,只需一条命令即可安装:
bash
pip install grpcio
出于开发目的,你可能还需要安装 Protocol Buffer 编译器支持:
bash
pip install grpcio-tools
如果在 Linux/macOS 上遇到权限错误,请使用 sudo pip install grpcio。Windows 用户应以管理员身份运行 pip.exe。请注意,Windows 和 macOS 需要较新版本的 pip 才能从 PyPI 检索正确的 wheel 包,因此请确保在安装前已升级 pip。
来源:src/python/grpcio/README.rst, README.md
C++ 安装
C++ 需要从源代码构建或使用包管理器。对于大多数用户,推荐的方法是使用预构建的包或使用 CMake 构建:
Linux 上的先决条件:
bash
sudo apt-get install build-essential autoconf libtool pkg-config cmake
macOS 上的先决条件:
bash
xcode-select --install
brew install autoconf automake libtool shtool cmake
克隆并构建:
bash
git clone -b v1.60.0 https://github.com/grpc/grpc
cd grpc
git submodule update --init
mkdir cmake/build && cd cmake/build
cmake -DCMAKE_CXX_STANDARD=17 ../..
make
其他语言安装
| 语言 | 安装方法 | 命令 |
|---|---|---|
| Go | Package Manager | go get google.golang.org/grpc |
| Node.js | NPM | npm install @grpc/grpc-js |
| Java | Maven Central | 将依赖项添加到 pom.xml |
| C#/.NET | NuGet | Install-Package Grpc.Net.Client |
| Ruby | Gem | gem install grpc |
| PHP | PECL | pecl install grpc |
来源:README.md
创建你的第一个 gRPC 服务
任何 gRPC 应用程序的基础是定义服务接口的 .proto 文件。让我们创建一个简单的问候服务,它接受一个名字并返回一条个性化消息。
在 Protocol Buffers 中定义服务
创建一个名为 helloworld.proto 的文件,包含以下服务定义:
protobuf
syntax = "proto3";
package helloworld;
// The greeting 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;
}
此定义创建了一个 Greeter 服务,其中包含一个 RPC 方法 SayHello,该方法接受 HelloRequest 并返回 HelloReply。syntax = "proto3" 声明表明我们正在使用 Protocol Buffers 第 3 版,它更简单且得到更广泛的支持。
来源:examples/protos/helloworld.proto
生成服务器和客户端代码
使用 Protocol Buffer 编译器从你的 .proto 文件生成特定语言的代码。
Python:
bash
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. helloworld.proto
这将生成两个文件:helloworld_pb2.py(消息类)和 helloworld_pb2_grpc.py(客户端和服务器类)。
C++:
bash
protoc --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` helloworld.proto
protoc --cpp_out=. helloworld.proto
始终将生成的代码保留在版本控制中。这可以确保跨环境的一致构建,并避免在部署期间依赖 protoc 编译器。
来源:examples/python/helloworld, examples/cpp/helloworld
实现服务器
现在我们已经生成了代码,让我们实现将响应客户端请求的服务器。
Python 服务器实现
python
from concurrent import futures
import grpc
import helloworld_pb2
import helloworld_pb2_grpc
class Greeter(helloworld_pb2_grpc.GreeterServicer):
def SayHello(self, request, context):
return helloworld_pb2.HelloReply(message=f"Hello, {request.name}!")
def serve():
port = "50051"
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
server.add_insecure_port("[::]:" + port)
server.start()
print(f"Server started, listening on {port}")
server.wait_for_termination()
if __name__ == "__main__":
serve()
服务器实现创建了一个用于处理并发请求的线程池,注册了我们的服务实现,并开始在端口 50051 上监听。GreeterServicer 类重写了 SayHello 方法以提供我们的自定义问候逻辑。
来源:examples/python/helloworld/greeter_server.py
C++ 服务器实现
cpp
#include <grpcpp/grpcpp.h>
#include "helloworld.grpc.pb.h"
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;
using helloworld::Greeter;
using helloworld::HelloReply;
using helloworld::HelloRequest;
class GreeterServiceImpl final : public Greeter::Service {
Status SayHello(ServerContext* context, const HelloRequest* request,
HelloReply* reply) override {
std::string prefix("Hello ");
reply->set_message(prefix + request->name());
return Status::OK;
}
};
void RunServer() {
std::string server_address = "0.0.0.0:50051";
GreeterServiceImpl service;
ServerBuilder builder;
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
builder.RegisterService(&service);
std::unique_ptr<Server> server(builder.BuildAndStart());
std::cout << "Server listening on " << server_address << std::endl;
server->Wait();
}
int main() {
RunServer();
return 0;
}
C++ 服务器遵循类似的模式,但使用 gRPC C++ API,该 API 通过编译代码提供类型安全性和更好的性能。GreeterServiceImpl 类继承自生成的 Greeter::Service 基类并实现 SayHello 方法。
来源:examples/cpp/helloworld/greeter_server.cc
实现客户端
服务器运行后,让我们创建一个客户端来进行 RPC 调用。
Python 客户端实现
python
import grpc
import helloworld_pb2
import helloworld_pb2_grpc
def run():
print("Will try to greet world...")
with grpc.insecure_channel("localhost:50051") as channel:
stub = helloworld_pb2_grpc.GreeterStub(channel)
response = stub.SayHello(helloworld_pb2.HelloRequest(name="you"))
print(f"Greeter client received: {response.message}")
if __name__ == "__main__":
run()
客户端创建一个连接到服务器的通道,从生成的客户端代码创建一个 stub,并像调用本地函数一样调用 SayHello 方法。RPC 调用返回一个我们可以直接访问的 HelloReply 消息。
来源:examples/python/helloworld/greeter_client.py
C++ 客户端实现
cpp
#include <grpcpp/grpcpp.h>
#include "helloworld.grpc.pb.h"
#include <memory>
#include <string>
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using helloworld::Greeter;
using helloworld::HelloReply;
using helloworld::HelloRequest;
class GreeterClient {
public:
GreeterClient(std::shared_ptr<Channel> channel)
: stub_(Greeter::NewStub(channel)) {}
std::string SayHello(const std::string& user) {
HelloRequest request;
request.set_name(user);
HelloReply reply;
ClientContext context;
Status status = stub_->SayHello(&context, request, &reply);
if (status.ok()) {
return reply.message();
} else {
return "RPC failed";
}
}
private:
std::unique_ptr<Greeter::Stub> stub_;
};
int main() {
GreeterClient greeter(
grpc::CreateChannel("localhost:50051", grpc::InsecureChannelCredentials()));
std::string reply = greeter.SayHello("world");
std::cout << "Greeter received: " << reply << std::endl;
return 0;
}
C++ 客户端将 gRPC stub 封装在一个方便的类中,该类处理通道创建和 RPC 调用。错误处理内置在每个 RPC 调用返回的 Status 对象中。
来源:examples/cpp/helloworld/greeter_client.cc
运行你的第一个 gRPC 应用程序
现在让我们将所有内容组合在一起并运行完整的应用程序。这个分步过程将演示完整的 gRPC 工作流程。
步骤 1:安装依赖项
bash
pip install grpcio grpcio-tools
步骤 2:从 Proto 定义生成代码
bash
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. helloworld.proto
步骤 3:启动服务器
bash
python greeter_server.py
# Output: Server started, listening on 50051
步骤 4:运行客户端
bash
# 在单独的终端中
python greeter_client.py
# Output: Will try to greet world...
# Output: Greeter client received: Hello, you!
对于开发,请使用 --python_out=. 标志在当前目录中生成 Python 文件。在生产环境中,将生成的代码组织在单独的包中,以保持整洁的项目结构。
来源:examples/python/helloworld/greeter_server.py, examples/python/helloworld/greeter_client.py
探索示例目录
grpc 仓库包含大量展示各种 gRPC 功能的示例。examples/ 目录按语言组织,并包含常见场景的实现:
examples/
├── cpp/ # C++ 示例(helloworld, route_guide, auth, compression)
├── python/ # Python 示例(helloworld, async_streaming, interceptors)
├── node/ # Node.js 示例(dynamic_codegen, static_codegen)
├── php/ # PHP 示例(greeter, route_guide)
├── ruby/ # Ruby 示例(greeter_client, pubsub)
├── protos/ # 共享的 Protocol Buffer 定义
└── objective-c/ # Objective-C 示例(helloworld, auth_sample)
每个语言目录都包含一个 helloworld 子目录,其中包含你刚刚实现的完整「Hello World」示例。除了基础知识之外,还可以探索:流式传输(hellostreamingworld/ 中的双向流式传输示例)、身份验证(auth/ 中的 TLS 和身份验证示例)、拦截器(用于日志记录和监控的请求/响应拦截器)、高级模式(重试、截止日期和负载均衡示例)。
来源:examples/README.md, examples/python
关键概念和后续步骤
现在你有了一个可运行的 gRPC 应用程序,以下是你遇到的基本概念以及接下来可以探索的内容:
| 概念 | 你学到了什么 | 在哪里了解更多 |
|---|---|---|
| Protocol Buffers | 在 .proto 文件中定义服务和消息 | Protocol Buffers and IDL |
| 服务器实现 | 扩展生成的服务基类 | Building and Installing gRPC |
| 客户端 Stubs | 使用生成的客户端代码进行 RPC 调用 | Language-Specific Setup Guides |
| 通道 | 建立与服务器的连接 | Client Channel Architecture |
| 流式传输 RPCs | 一元、客户端流、服务端流、双向流 | Streaming Semantics |
Hello World 示例演示了一元 RPC 模式(一个请求,一个响应)。gRPC 还支持其他三种流式传输模式:客户端流式传输(客户端发送多个请求,服务器返回一个响应)、服务端流式传输(客户端发送一个请求,服务器返回响应流)、双向流式传输(客户端和服务器都发送消息流)。这些流式传输模式对于实时应用程序、大文件传输和事件驱动架构至关重要。hellostreamingworld/ 示例演示了这些模式的实际应用。
来源:examples/protos/helloworld.proto, examples/python/hellostreamingworld
常见问题排查
开始使用 gRPC 时,你可能会遇到一些常见问题:
| 问题 | 症状 | 解决方案 |
|---|---|---|
| 端口已被占用 | Failed to bind to address | 使用不同的端口或停止冲突的服务 |
| 导入错误 | ModuleNotFoundError: No module named 'grpc' | 验证 pip install grpcio 是否已成功完成 |
| 找不到 Protoc | protoc: command not found | 从 protobuf 版本中安装 Protocol Buffer 编译器 |
| 连接被拒绝 | 客户端无法连接到服务器 | 确保服务器正在运行且防火墙允许端口 50051 |
| 缺少生成的代码 | 构建失败并出现缺少的导入 | 验证 protoc 命令是否已使用正确的标志成功运行 |
有关更详细的故障排除指南,请参阅故障排除指南和你所选语言的特定语言设置指南。
来源:TROUBLESHOOTING.md, src/python/grpcio/README.rst
后续步骤
恭喜!你已成功构建并运行了你的第一个 gRPC 应用程序。为了加深你的理解并构建可用于生产环境的服务,请继续使用以下资源:Hello World 示例 (探索多种语言的完整示例及详细解释)、构建和安装 gRPC (了解高级构建配置和生产部署)、特定语言设置指南 (获取你首选语言的详细设置说明)、gRPC 概念和架构(了解底层原理和设计决策)。有关包括教程、最佳实践和参考材料在内的综合文档,请访问 gRPC 官方文档。
构建和安装 gRPC
本指南提供了从源代码构建和安装 gRPC 的全面说明,专为需要超越基本软件包安装、了解构建架构的中级开发者量身定制。gRPC 支持多种构建系统,以适应不同的开发工作流程和平台要求。本文档涵盖了推荐的构建方法、依赖管理策略以及特定平台的注意事项。
构建系统架构
gRPC 采用多构建系统架构,以支持不同的开发场景和平台要求。主要的构建系统是 Bazel,CMake 是偏好传统 C/C++ 构建工作流程的用户的推荐替代方案。旧的 Make 系统仍然可用,但已弃用。
来源:BUILDING.md, CMakeLists.txt, doc/bazel_support.md
先决条件和平台设置
在构建 gRPC 之前,请确保你的开发环境满足特定平台的要求。这些先决条件在 Linux、macOS 和 Windows 系统上各不相同。
Linux 平台
Linux 系统需要基本的构建工具,并且根据你选择的构建系统,可能需要额外的软件包。
安装基本工具的核心命令:
sh
[sudo] apt-get install build-essential autoconf libtool pkg-config
对于基于 CMake 的构建:[sudo] apt-get install cmake
对于运行清理器构建的 Contributor:[sudo] apt-get install clang libc++-dev
来源:BUILDING.md
macOS 平台
macOS 需要 Xcode Command Line Tools 和来自 Homebrew 的额外构建工具:
sh
[sudo] xcode-select --install
brew install autoconf automake libtool shtool
对于 CMake:从 cmake.org/download 安装。
重要提示:构建时,显式设置 LIBTOOL 环境变量以确保使用 Homebrew 安装的版本:
sh
LIBTOOL=glibtool LIBTOOLIZE=glibtoolize make
来源:BUILDING.md
Windows 平台
Windows 构建需要 Visual Studio、CMake 以及用于加密操作的特定依赖项:
| 组件 | 用途 | 安装 |
|---|---|---|
| Visual Studio 2022+ | C/C++ 编译器 | 从 Microsoft 下载 |
| Git | 版本控制 | https://git-scm.com/ |
| CMake | 构建系统 | https://cmake.org/download/ |
| nasm | BoringSSL 汇编 | choco install nasm |
| Ninja | 更快的构建(可选) | choco install ninja |
来源:BUILDING.md
仓库克隆和子模块管理
gRPC 通过 Git 子模块管理依赖项。正确的仓库初始化对于成功构建至关重要。
Unix 系统:
sh
git clone -b RELEASE_TAG_HERE https://github.com/grpc/grpc
cd grpc
git submodule update --init
Windows 系统:
cmd
git clone -b RELEASE_TAG_HERE https://github.com/grpc/grpc
cd grpc
git submodule update --init
关键说明:Bazel 构建系统使用不同的依赖模型,不需要初始化子模块。子模块仅对于 CMake 和 Make 构建是必需的。
来源:BUILDING.md
构建系统选项和比较
| 构建系统 | 状态 | 用例 | 构建速度 | 开发者体验 | 平台支持 |
|---|---|---|---|---|---|
| Bazel | 主要/推荐 | gRPC Contributor,大型项目 | 最快 | 最佳功能,可重现构建 | Linux, macOS, Windows |
| CMake | 替代方案 | 集成到 CMake 项目,传统工作流程 | 快 | 标准 C/C++ 工作流程 | Linux, macOS, Windows |
| Make | 已弃用 | 旧版本兼容 | 较慢 | 手动配置 | 仅 Unix |
Bazel 提供了最快、最可靠的构建体验,具备封闭构建、远程缓存和无缝跨平台支持等高级功能。然而,对于现有的基于 CMake 的项目,CMake 提供了更好的集成。
来源:BUILDING.md, doc/bazel_support.md
使用 Bazel 构建(推荐)
Bazel 是 gRPC C++ 的主要构建系统,提供更快、更整洁的构建体验。gRPC 支持 Bazel 8.0.1 和 7.4.1 版本。
sh
bazel build :all
# Run all C/C++ tests
bazel test --config=dbg //test/...
重要兼容性说明:如果使用 Bazel 7 或更新版本,你必须禁用 bzlmod:bazel build --enable_bzlmod=false :all
来源:BUILDING.md, doc/bazel_support.md
使用 CMake 构建
Linux/Unix 使用 Make:
sh
mkdir -p cmake/build
cd cmake/build
cmake -DCMAKE_CXX_STANDARD=17 ../..
make
要构建共享库(.so 文件):cmake -DBUILD_SHARED_LIBS=ON
Windows 使用 Visual Studio 2022+:
cmd
md .build
cd .build
cmake -G "Visual Studio 17 2022" -DCMAKE_CXX_STANDARD=17 ..
cmake --build . --config Release
Windows 使用 Ninja(更快):
cmd
cd cmake
md build
cd build
call "%VS140COMNTOOLS%..\..\VC\vcvarsall.bat" x64
cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=17 ..\..
cmake --build .
来源:BUILDING.md
使用 CMake 提供者管理依赖
| 提供者模式 | 行为 | 来源位置 | 用例 |
|---|---|---|---|
| module | 与 gRPC 并行构建依赖 | third_party/ 中的 Git 子模块 | 开发,Contributor 构建 |
| package | 使用系统安装的库 | 系统包管理器或 CMAKE_INSTALL_PREFIX | 生产,系统集成 |
支持的依赖:gRPC_ZLIB_PROVIDER、gRPC_CARES_PROVIDER、gRPC_RE2_PROVIDER、gRPC_SSL_PROVIDER、gRPC_PROTOBUF_PROVIDER、gRPC_ABSL_PROVIDER。
系统包示例配置:
sh
cmake ../.. -DgRPC_INSTALL=ON \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_STANDARD=17 \
-DgRPC_ABSL_PROVIDER=package \
-DgRPC_CARES_PROVIDER=package \
-DgRPC_PROTOBUF_PROVIDER=package \
-DgRPC_RE2_PROVIDER=package \
-DgRPC_SSL_PROVIDER=package \
-DgRPC_ZLIB_PROVIDER=package
来源:BUILDING.md, CMakeLists.txt
C++ 标准一致性
从 gRPC C++ 1.70 开始,所有 CMake 构建必须使用 C++17 或更高版本。gRPC C++ 1.70 需要 C++17;Abseil 根据 C++ 版本提供不同 API;版本不一致会导致 API 不匹配和构建失败。使用 DCMAKE_CXX_STANDARD=17 可确保兼容性。
来源:BUILDING.md
使用 CMake 安装
sh
cmake ../.. -DgRPC_INSTALL=ON -DCMAKE_INSTALL_PREFIX=/usr/local
make
make install
CMake 3.13+ 可在「module」模式下一步安装依赖;生产部署建议使用「package」模式。
来源:BUILDING.md
使用 Make 构建(已弃用)
基于 Make 的构建系统已弃用。新项目应使用 Bazel 或 CMake。
sh
# From grpc repository root
make
常见错误:若遇到 aclocal-1.15: command not found,可执行 git clean -f -d -x && git submodule foreach --recursive git clean -f -d -x 后重新安装先决条件再 make。
来源:BUILDING.md, Makefile
项目结构概览
grpc/
├── BUILD # Bazel 构建配置
├── CMakeLists.txt # CMake 构建配置
├── Makefile # Make 构建配置(已弃用)
├── BUILDING.md # 本构建指南
├── cmake/ # CMake 模块和依赖脚本
├── third_party/ # 依赖项的 Git 子模块
├── src/ # 核心与 C++ 库
├── examples/ # 示例应用程序
└── test/ # 测试套件
构建系统选择指南
| 场景 | 推荐的构建系统 | 理由 |
|---|---|---|
| gRPC Contributor | Bazel | 最佳开发者体验,最快构建速度 |
| 大型项目 | Bazel | 封闭构建,远程缓存,可重现性 |
| 基于 CMake 的项目 | CMake | 无缝集成,熟悉的工作流程 |
| 跨平台部署 | CMake | 广泛的平台支持,工具链文件 |
| 快速原型设计 | CMake | 简单配置,通用知识 |
| 旧系统 | Make | 已弃用,但可用于兼容性 |
来源:BUILDING.md, doc/bazel_support.md
后续步骤
成功构建 gRPC 后:Hello World 示例 、特定语言的设置指南 、gRPC 概念和架构 、快速开始。有关构建问题的故障排除,请参阅故障排除指南或贡献指南。
特定语言设置指南
本指南为 gRPC 在所有支持的编程语言中提供了全面的安装和设置说明。每种语言都有自己的包管理器约定、安装方法和针对其生态系统优化的构建系统集成。
语言支持架构
gRPC 的多语言架构由一个共享的 C++ 核心库 (src/core) 和构建在其之上的特定语言实现组成。各种语言要么直接在 grpc/grpc 仓库中维护其实现,要么维护单独的特定语言仓库。
来源:README.md
本仓库中的语言
C++ 设置
C++ 实现完全包含在 src/cpp 中。支持的平台包括 Linux (Debian, Ubuntu, CentOS)、Windows 10+、MacOS(x64, ARM64)等,构建系统为 Bazel 或 CMake。
Bazel(推荐用于开发):
bash
bazel_dep(name = "grpc", version = "1.72.0")
传统 WORKSPACE 可使用 http_archive 引入 gRPC 源码。
CMake(推荐用于生产):
cmake
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(gRPC CONFIG REQUIRED)
target_link_libraries(your_target gRPC::grpc++)
来源:src/cpp/README.md, BUILDING.md
Python 设置
bash
pip install grpcio
pip install grpcio-health-checking # 健康检查
pip install grpcio-reflection # 服务端反射
pip install grpcio-testing # 测试工具
包结构:grpcio(核心)、grpcio_health_checking、grpcio_reflection、grpcio_testing、grpcio_channelz。示例在 examples/python。
来源:README.md, examples/python/README.md
Ruby 设置
bash
gem install grpc
# 或 Gemfile: gem 'grpc', '~> 1.0'
需要 Ruby 3.x+。从源码构建需克隆仓库、安装 Ruby 3.x、bundler 后于 src/ruby 执行 bundle install 与 rake。
来源:src/ruby/README.md
PHP 设置
先决条件:PHP 7.1+、PECL、Composer。
bash
sudo pecl install grpc
从源码构建需先构建 gRPC C 核心,再在 src/php/ext/grpc 中 phpize、configure、make。php.ini 添加 extension=grpc.so。Composer:"grpc/grpc": "~1.30.0"。
来源:src/php/README.md
Objective-C 设置
支持 iOS 15+、macOS 11+、tvOS 13+、watchOS 6+、visionOS 1.0。使用 CocoaPods,依赖 !ProtoCompiler-gRPCPlugin 等,通过 Podspec 的 prepare_command 从 .proto 生成 Objective-C 代码。示例在 examples/objective-c/。
来源:src/objective-c/README.md
C#/.NET 设置
传统 Grpc.Core 处于维护模式。现代安装:
bash
dotnet add package Grpc.Net.Client
dotnet add package Grpc.AspNetCore.Server
# 或 NuGet: Install-Package Grpc.Net.Client, Grpc.AspNetCore.Server
来源:src/csharp/README.md
外部语言仓库
| 语言 | 安装/依赖 | 仓库 |
|---|---|---|
| Go | go get google.golang.org/grpc |
grpc-go |
| Java | Maven: io.grpc:grpc-netty-shaded:1.60.0 | grpc-java |
| Kotlin | implementation("io.grpc:grpc-kotlin-stub:1.4.1") |
grpc-kotlin |
| Node.js | npm install @grpc/grpc-js |
grpc-node |
| Dart | pubspec: grpc: ^3.2.0 |
grpc-dart |
| WebJS | --- | grpc-web |
来源:README.md
语言对比矩阵
| 语言 | 包管理器 | 代码生成 | 流式传输 | 异步支持 | 平台支持 |
|---|---|---|---|---|---|
| C++ | Bazel/CMake | protoc | ✅ | C++20 协程 | Linux, Windows, macOS, iOS, Android |
| Python | pip | protoc | ✅ | asyncio | 所有主要平台 |
| Ruby | gem | protoc | ✅ | Fibers | 所有主要平台 |
| PHP | PECL/Composer | protoc | ✅ | 标准 | 所有主要平台 |
| Objective-C | CocoaPods | protoc | ✅ | GCD | iOS, macOS, tvOS, watchOS, visionOS |
| Go | go modules | protoc-gen-go | ✅ | goroutines | 所有主要平台 |
| Java | Maven | protoc | ✅ | Reactor/RxJava | 所有主要平台 |
| Kotlin | Maven/Gradle | protoc | ✅ | 协程 | JVM 平台 |
| Node.js | npm | protoc | ✅ | Promises/async | 所有主要平台 |
| Dart | pub | protoc | ✅ | async/await | Flutter, Web, Server |
| C# (.NET) | NuGet | protoc | ✅ | async/await | .NET 平台 |
安装决策流程与先决条件摘要
选择合适的语言需考虑:现有基础设施、性能要求、开发效率、平台限制、团队专业知识。所有 gRPC 实现可互操作。
| 语言 | 运行时版本 | 构建工具 | 包管理器 |
|---|---|---|---|
| C++ | --- | Bazel 1.0+, CMake 3.13+ | Bazel, CMake |
| Python | 3.6+ | pip, setuptools | pip |
| Ruby | 3.1+ | bundler, rake | gem |
| PHP | 7.1+ | pecl, composer | pecl, composer |
| Objective-C | Swift 5.0+ | Xcode, CocoaPods | CocoaPods |
| Go | 1.16+ | Go modules | go get |
| Java | 8+ | Maven, Gradle | Maven Central |
| Kotlin | 1.5+ | Maven, Gradle | Maven Central |
| Node.js | 12+ | npm, yarn | npm |
| Dart | 2.12+ | pub | pub |
| C# | .NET 5+ or Core 3.1+ | dotnet CLI | NuGet |
后续步骤
安装后继续:快速入门 、Hello World 示例 、构建和安装 gRPC 、gRPC 概念和架构。详细示例见官方 gRPC 文档。
Hello World 示例
本指南提供具体的、特定语言的实现,帮助你快速理解并运行 gRPC 服务:构建一个简单客户端-服务器应用,客户端发送名字并接收个性化问候。
你将学到什么
- 使用 Protocol Buffers 定义服务接口
- 实现服务器端服务逻辑
- 创建客户端以调用远程过程
- 理解同步和异步通信模式
- 在多种编程语言中运行示例
Protocol Buffer 定义
所有 Hello World 示例共享以下 .proto 定义:
protobuf
syntax = "proto3";
package helloworld;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
rpc SayHelloStreamReply (HelloRequest) returns (stream HelloReply) {}
rpc SayHelloBidiStream (stream HelloRequest) returns (stream HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
包含三个 RPC:SayHello (一元)、SayHelloStreamReply (服务器流式)、SayHelloBidiStream(双向流式)。来源:examples/protos/helloworld.proto
可用的语言实现
| 语言 | 目录 | 特性 | 复杂度 |
|---|---|---|---|
| C++ | examples/cpp/helloworld/ | 同步, 异步, 回调, XDS | 初级-中级 |
| Python | examples/python/helloworld/ | 同步, 异步, 反射, 优雅停机 | 初级 |
| Ruby | examples/ruby/ | 带信号处理的同步 | 初级 |
| Objective-C | examples/objective-c/helloworld/ | iOS/macOS with CocoaPods | 中级 |
| Android | examples/android/helloworld/ | 带 Gradle 的原生 Android | 中级 |
| PHP | examples/php/ | 快速入门和基础 | 初级 |
C++ 实现要点
同步服务器实现 Greeter::Service,在端口 50051 监听,可启用健康检查和反射。同步客户端创建 Channel 和 Stub 调用 SayHello。
bash
cd examples/cpp/helloworld
make
./greeter_server # 终端1
./greeter_client # 终端2
高级变体:greeter_callback_client.cc、xds_greeter_client.cc。来源:examples/cpp/helloworld/
Python 实现要点
同步服务器使用 GreeterServicer、线程池;客户端使用 insecure_channel 和 Stub。异步客户端使用 grpc.aio.insecure_channel 与 async/await。
bash
cd examples/python/helloworld
python greeter_server.py &
python greeter_client.py
高级:greeter_server_with_reflection.py、async_greeter_server_with_graceful_shutdown.py。
Ruby / Objective-C / 跨语言
Ruby:GRPC::RpcServer、add_http2_port、handle(GreeterServer),s.run_till_terminated_or_interrupted([1, 'int', 'SIGTERM'])。Objective-C:pod install 后运行,需另启一种语言的服务器。跨语言测试:用 C++ 起服务器,用 Python、Ruby 客户端连接,均可收到问候。
项目结构概览
examples/
├── protos/helloworld.proto
├── cpp/helloworld/ (greeter_server.cc, greeter_client.cc, Makefile)
├── python/helloworld/ (greeter_server.py, greeter_client.py, helloworld_pb2.py)
└── ruby/ (greeter_server.rb, greeter_client.rb)
常见问题排查
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
| Connection refused | 服务器未运行 | 先启动服务器 |
| Port already in use | 端口占用 | 终止旧进程或换端口 |
| Module not found | 依赖未安装 | 安装对应语言依赖 |
| Protobuf not generated | 缺少构建步骤 | 从 .proto 重新生成 |
后续步骤
gRPC 概念和架构 、Protocol Buffers 和 IDL 、同步/异步 RPC 模式 。语言细节见特定语言设置指南。
最新更新和发布计划
本页面跟踪 gRPC 的最新进展、实验性功能以及发布路线图。2026 年 1 月的最近提交反映了在 C++ 核心、Python 绑定、负载均衡策略和可观测性功能方面的持续改进。
近期重要更新(2026 年 1 月)
- 许可证范围澄清:LICENSE 中明确 MPL v2.0 与 BSD 3-Clause 仅适用于特定文件,避免歧义。
- 负载均衡改进:pick_first_ready_to_connecting 实验已启用;RR/WRR 从随机索引开始连接以分散流量。
- 客户端通道 API:ConfigSelector 改为针对每次 RPC 返回过滤器链,为 xDS 按路由独立过滤器链做准备。
实验状态概览
| 实验 | 状态 | 目标版本 |
|---|---|---|
| event_engine_poller_for_python | 计划推出 | ~1.80 |
| call_tracer_in_transport | OSS 已启用,内部受阻 | TBD |
| error_flatten, rr_wrr_connect_from_random_index | 内部已推出 | 再经一个 OSS 版本 |
| pick_first_ready_to_connecting | 内部推出 | 直至内部推出完成 |
| subchannel_wrapper_cleanup_on_orphan | 内部推出 | 内部推出之后 |
| subchannel_connection_scaling | 尚未完全落地 | 时间表延长 |
特定语言与构建更新
- Python:移除 six 库;GRPC_ENABLE_FORK_SUPPORT 在核心与 Python 中均默认禁用。
- C++:Status 优化(移动字符串);新增 SNI 覆盖选项;Channelz V2 设为默认。
- 构建:Bazel 9 兼容;bzlmod 中支持 @google_cloud_cpp;rules_proto 7.1.0。
发布计划考量
Python 3.14 支持与 EventEngine 实验计划在 1.80 左右推出;功能采用先内部后 OSS 的渐进式推出;资源管理(线程池、连接扩展、负载均衡)持续优化;持续移除旧依赖与旧代码路径。
跟踪更新:监控 grpc/grpc 仓库提交、未解决问题、已解决问题。
安全审计发现和修复
本页面记录 gRPC 与安全相关的发现、修复及持续问题。项目未维护公开的中心安全审计报告或 CVE 页面,安全沟通分散在 GitHub issues、PR 和提交消息中。
最近提交中的安全相关修复
- 许可证范围澄清 (2026-01):澄清 MPL/BSD 仅适用于特定文件,降低法律风险。
- Python Fork 支持对齐 (2026-01):核心与 Python 对 GRPC_ENABLE_FORK_SUPPORT 默认一致,两处均默认禁用 fork 支持,避免混合状态导致的进程安全问题。
- Channelz 竞态条件修复 (2026-01):修复 channelz 诊断子系统中的竞态,降低 DoS/信息泄露风险。
- 线程池:Issue #41169 指出 EventEngine 线程池在负载下可能无限增长,属资源耗尽/DoS 向量,PR #41170 提议上限,问题仍开放。
持续存在的安全问题
| 问题类型 | 参考 | 状态 | 严重程度 | 受影响版本 |
|---|---|---|---|---|
| 内存安全崩溃 (macOS/iOS) | #41250 | 开放 | 高 | 1.69.0 |
| Keepalive 执行差距 (gRFC A8) | #32912 | 开放 | 中 | 所有 |
| Fork 处理程序死锁 | #37710 | 开放 | 中 | Python 1.66.0+ |
| 线程池耗尽 | #41169 | 开放 | 中 | 所有 |
安全最佳实践
- 避免多线程进程中 fork :必要时
export GRPC_ENABLE_FORK_SUPPORT=0,或使用进程生成。 - Keepalive 间隔:在 #32912 修复前,应用层强制执行 ≥10 秒(gRFC A8)。
- 监控线程池:对 gRPC 相关线程数设告警,防止无界增长。
- 固定稳定版本:macOS/iOS 可考虑固定到已验证稳定版本。
- 安全报告:勿公开开 issue;可向 security@google.com 报告,主题含 "gRPC security",留 90 天披露协调。
社区反馈和问题
gRPC 跨多种语言的活跃用户群带来从严重崩溃到 API 设计不一致等各类问题。通过 issue 与提交历史可见以下模式。
关键问题
- C++ 核心在 macOS 上崩溃 (#41250) :Firebase iOS SDK 使用 gRPC-C++ 1.69.0 时在
grpc_slice_refcount::Ref/SliceBuffer::RefSlice崩溃,堆栈涉及 EventEngine PosixEndpointImpl::TcpFlush,疑为释放后使用或竞态。 - Python 测试不稳定性 (#37710):Apache Beam 升级到 grpcio 1.66.0 后测试大量失败(连接错误/挂起、fork 相关警告);近期提交在核心与 Python 中统一默认禁用 fork 支持以应对。
特定语言与平台
- Python API:Metadata 的 keys()/values()/items() 行为不符合预期;缺少类型注解;UnaryUnaryCallResponse.add_done_callback 在异步路径引发 NotImplementedError。
- 平台:Ruby 4 平台 gems、Python 3.14 自由线程 wheels、PHP 8.5 兼容性等需求或问题在跟踪中。
核心架构
- 无限制线程增长 (#41169):WorkStealingThreadPool 在负载下动态创建线程且不回收,高负载下线程数可增至 200+,对容器化环境不利;PR #41170 提议可配置上限。
- Keepalive 不符合 gRFC (#32912):gRFC A8 要求最短 10 秒保活间隔,实现仍接受 1 秒,问题自 2023 年 4 月开放。
维护者响应模式
保守默认(如 fork 默认禁用)、实验过期机制、许可证澄清、内部先于 OSS 的推出节奏。近期已关闭异步回调误用类 issue (#41213),并推进构建(bzlmod)、Python 现代化(移除 six)、性能与负载均衡改进。
gRPC 概念和架构
本页介绍 gRPC 的基本概念和架构设计:什么是 gRPC、如何工作,以及支持分布式服务高效通信的关键组件。
什么是 gRPC?
gRPC 是现代、高性能的 RPC 框架,使应用在不同语言与平台间高效通信。核心是与语言无关的服务定义并生成客户端/服务端代码,从而简化分布式系统构建。原则:一次定义接口,生成多语言代码,由 gRPC 处理通信复杂性。
来源:CONCEPTS.md
核心架构概览
采用分层设计:高级语言 API 构建于共享 C 核心库之上。核心库提供协议逻辑,所有语言实现依赖同一核心。好处:代码复用、协议一致性、高性能、可维护性(协议更新只需改核心一次)。
来源:src/core/README.md, CONCEPTS.md
使用 Protocol Buffers 定义接口
服务在 .proto 中定义,包含:服务声明 (RPC 方法)、请求/响应消息 。示例见 helloworld.proto:SayHello(一元)、SayHelloStreamReply(服务端流)、SayHelloBidiStream(双向流)。
流式语义与 RPC 类型
| RPC 类型 | 描述 | 用例 |
|---|---|---|
| Unary (一元) | 单请求,单响应 | 简单查询、命令 |
| Server Streaming | 单请求,响应流 | 下载、实时更新 |
| Client Streaming | 请求流,单响应 | 上传、批处理 |
| Bidirectional Streaming | 双方均发送流 | 聊天、实时协作 |
来源:CONCEPTS.md
同步与异步 API
- 同步:阻塞直到响应到达,易理解、易调试、自然错误处理;适合简单请求-响应与原型。
- 异步:非阻塞、高并发、事件驱动;适合高并发、实时、多调用并发。不需要高并发时选同步以简化实现。
来源:examples/cpp/helloworld/greeter_client.cc, CONCEPTS.md
基于 HTTP/2 的 gRPC 协议
调用结构:Request = Request-Headers → *Length-Prefixed-Message → EOS;Response = Response-Headers → *Length-Prefixed-Message → Trailers。Request-Headers 含 :method POST、:path /ServiceName/MethodName、content-type application/grpc、grpc-timeout、自定义元数据。消息格式:Compressed-Flag (1B) + Message-Length (4B) + Message。
HTTP/2 优势:多路复用(单连接多并发)、二进制分帧、HPACK 头部压缩、流量控制、服务端推送。来源:doc/PROTOCOL-HTTP2.md
流量控制机制
连接级与流级流量控制,用于管理缓冲与反向压力,防止内存耗尽。来源:CONCEPTS.md
关键架构组件
- Channel:到服务器端点的抽象,负责名称解析、负载均衡、连接管理、凭证。
- Stub:客户端侧类型安全接口,序列化/反序列化、上下文与元数据、同步/异步。
- Service:服务端实现 .proto 中定义的方法,接收请求、执行业务逻辑、返回或流式响应。
- Server Context:每次调用的元数据、截止时间、认证、取消信号。
- Transport Layer:HTTP/2 帧编解码、HPACK、流量控制、连接管理。
来源:CONCEPTS.md
项目结构概览
grpc/
├── src/core/ (channel, server, transport, load_balancing, resolver)
├── examples/ (protos, cpp, python, ...)
├── doc/ (PROTOCOL-HTTP2.md 等)
└── include/ (公共 API 头文件)
总结与下一步
接口优先、四种流式 RPC、同步/异步 API、HTTP/2 基础、分层架构。推荐继续:Protocol Buffers and IDL 、Hello World Examples 、Abstract gRPC Protocol Specification 、HTTP/2 Implementation Details 、Client Channel Architecture。
Protocol Buffers 和 IDL
gRPC 使用 Protocol Buffers 作为接口定义语言 (IDL),从单一 .proto 生成多语言客户端/服务端代码,保证类型安全与跨语言契约。
IDL 语法与消息定义
proto3 语法包含:包声明、服务定义(RPC 方法及流式语义)、消息定义。字段分配唯一编号 (1,2,3...),用于二进制编码与向后兼容。支持 string、int32、int64、bool、float、double、bytes、嵌套消息、枚举、repeated、oneof、map。
RPC 与流式语义
- 一元:
rpc SayHello (HelloRequest) returns (HelloReply) {} - 服务端流:
returns (stream Feature) - 客户端流:
rpc RecordRoute(stream Point) returns (RouteSummary) - 双向流:
rpc RouteChat(stream RouteNote) returns (stream RouteNote)
代码生成与构建
Bazel:grpc_proto_library 或拆分为 proto_library、cc_proto_library、cc_grpc_library(grpc_only=True)。Python:py_proto_library、py_grpc_library。C++ 产物:.pb.h/.pb.cc、.grpc.pb.h/.grpc.pb.cc。
其他要点
- 众所周知类型:Empty、Timestamp、Duration、Any 等。
- 服务器反射协议:运行时发现服务与方法签名,便于调试与 CLI。
- 内部协议:src/proto/grpc/ 下 Channelz、Health、Load Balancing、Reflection、Status、Testing。
- 最佳实践:字段 1--15 给高频字段;包组织清晰;服务按领域聚合;流式按数据量与时效选择。
来源:CONCEPTS.md, examples/protos/, doc/server-reflection.md
gRPC 协议规范摘要
gRPC 抽象协议定义请求/响应的通用结构(与 HTTP/2 映射在 PROTOCOL-HTTP2.md 中):Request = Request-Headers + *Length-Prefixed-Message + EOS;Response = Response-Headers + *Length-Prefixed-Message + Trailers 或 Trailers-Only。Length-Prefixed-Message = Compressed-Flag (1B) + Message-Length (4B) + Message。详见 HTTP/2 实现细节 与 doc/PROTOCOL-HTTP2.md。
HTTP/2 实现细节
gRPC 的 HTTP/2 实现基于 RFC 9113,位于 CHTTP2 传输层 (src/core/ext/transport/chttp2/transport/),提供帧解析与序列化、流生命周期、HPACK、流量控制、连接状态协调。
请求/响应格式
Request-Headers 必含::method POST、:scheme、:path /ServiceName/MethodName、:authority;可选 grpc-timeout、content-type application/grpc、grpc-encoding、grpc-accept-encoding 等。响应含 :status 200、grpc-status、grpc-message、grpc-status-details-bin。EOS 由 END_STREAM 指示。
消息分帧与流管理
Length-Prefixed-Message 封装在 DATA 帧中;单条消息可跨多 DATA 帧,单 DATA 帧可含多条消息。GrpcMessageAssembler 负责重组。流状态:Idle → Open → HalfClosedLocal/Remote → Closed。Stream 类封装调用处理器、流状态机、头部组装器、数据队列、每流流量控制。
HPACK 与流量控制
HPACK 编码器/解析器、动态表、二进制头部 (-bin) Base64 解码。流量控制:连接级与流级;常量如 kDefaultWindow 65535、kMaxWindow 2³¹-1;FlowControlAction 含 UPDATE_IMMEDIATELY/QUEUE_UPDATE 等。设置:标准 HTTP/2 设置 + gRPC 扩展(GRPC_ALLOW_TRUE_BINARY_METADATA 等)。
连接管理与错误
GOAWAY 优雅关闭;PING 保活与延迟检测。连接失败:客户端侧调用得 UNAVAILABLE,服务端侧得 CANCELLED。HTTP/2 错误码映射到 gRPC 状态(如 REFUSED_STREAM→UNAVAILABLE、CANCEL→CANCELLED)。TLS 1.2+、SNI、头部大小限制(如 8 KiB)。User-Agent 格式:grpc-Language/Version。
来源:doc/PROTOCOL-HTTP2.md, src/core/ext/transport/chttp2/
流控机制
gRPC 基于 HTTP/2 实现连接级 与流级双层流量控制,防止接收方过载并随网络条件动态调整吞吐量。基于信用的窗口通过 WINDOW_UPDATE 补充,窗口上限 2³¹-1 字节。
架构:TransportFlowControl 管理连接级窗口,使用 BdpEstimator 做带宽时延积估算;各流由 StreamFlowControl 管理。关键常量:默认窗口 65535、默认帧大小 16384、最大窗口 2³¹-1、最大窗口增量 2²⁰。IncomingUpdateContext/OutgoingUpdateContext 分别跟踪接收与发送的令牌。流窗口:stream_window = stream.remote_window_delta + peer_settings.initial_window_size。FlowControlAction 含 UPDATE_IMMEDIATELY、QUEUE_UPDATE 等紧急程度。BDP 估算周期默认 8 秒。停滞检测:remote_window_delta + peer_initial_window_size <= 0 时认为流停滞。与内存配额集成以应对内存压力。
来源:doc/PROTOCOL-HTTP2.md, flow_control.h
C++ 核心库内部
C++ 核心采用分层与过滤器栈设计:表面层(C API)→ 通道栈(过滤器链)→ 传输层(grpc_transport)→ I/O(iomgr / Event Engine)。
通道过滤器 :grpc_channel_filter 定义 init_call_elem、destroy_call_elem、start_transport_stream_op_batch、start_transport_op 等。过滤器包括 auth、负载均衡、重试、压缩、deadline、logging。CallCombiner 串行化单次调用的操作。调用生命周期 :配置 → 调用 → 活动 → 完成;与 Arena 关联做高效内存管理;取消通过 CancelWithStatus/CancelWithError 传播。连接状态 :IDLE → CONNECTING → READY → TRANSIENT_FAILURE → SHUTDOWN。完成队列 :CompletionQueue 包装 grpc_completion_queue,支持 GRPC_CQ_NEXT/PLUCK、Next()/AsyncNext(),线程安全。I/O 与事件引擎 :iomgr 提供端点、轮询集、解析器、套接字工厂;Event Engine 提供闭包、任务句柄、连接句柄及自定义事件循环集成。内存:每调用一个 Arena,调用结束时整块释放。grpc_init()/grpc_shutdown() 显式初始化与关闭。
来源:src/core/, CONCEPTS.md
客户端通道架构
ClientChannel 是客户端侧统一入口,协调解析器 (发现后端地址)、负载均衡策略 (路由决策)、子通道 (到单后端的物理连接)与 ConfigSelector(每调用过滤器链与服务配置)。
通道状态 :IDLE → CONNECTING → READY → TRANSIENT_FAILURE → SHUTDOWN。调用路径 :StartCall → ConfigSelector.GetCallConfig → 过滤器链(含重试,默认可缓冲 256 KiB)→ SubchannelPicker 选子通道 → 传输。子通道 :SubchannelPoolInterface 管理池;支持 max_connections_per_subchannel;ConnectivityStateWatcherInterface 暴露状态;ThrottleKeepaliveTime 限制保活。过滤器链 :静态(client_channel、retry)与动态(ConfigSelector 按服务配置)。服务配置 :DefaultConfigSelector 从元数据解析调用路径,方法级重试/超时/元数据注入。解析器 :目标 URI → 地址列表 + 服务配置 + result_health_callback。操作经 work serializer 序列化(带 Locked 后缀)。高级:xDS 嵌套通道、DataProducerInterface、ChannelArgs。
来源:src/core/client_channel/, src/core/load_balancing/
传输层设计
传输层位于通道/表面层与网络 I/O 之间,将 RPC 转为协议帧。EndpointTransport 抽象;传输实现:chttp2(HTTP/2,生产)、chaotic_good(实验)、inproc(进程内)。
chttp2 生命周期 :grpc_create_chttp2_transport → start_reading;维护设置、流控窗口、活动流。流状态 :Idle → Open → HalfClosedLocal/Remote → Closed。流操作:EnqueueInitialMetadata、EnqueueMessage、EnqueueTrailingMetadata、EnqueueHalfClosed、EnqueueResetStream;DequeueFrames 在流控允许时取帧。流控 :TransportFlowControl/StreamFlowControl;FlowControlAction;BDP 估算;每 8 秒评估。帧处理 :HEADERS、DATA、SETTINGS、WINDOW_UPDATE、PING、RST_STREAM、GOAWAY;HEADER/CONTINUATION 部分处理以保持 HPACK 状态一致。写入 :WriteContext、WriteQuota、Chttp2WriteSizePolicy 自适应写大小。读取 :Http2ReadContext 支持 SetPauseReadLoop/ResumeReadLoopIfPaused。配置:TransportChannelArgs(keepalive、ping_timeout、max_header_list_size 等);协议协商 GRPC_ARG_TRANSPORT_PROTOCOLS 为实验性。ChannelZ 集成;HttpAnnotation 用于调用追踪。
来源:chttp2_transport.h, http2_transport.h, flow_control.h
同步 RPC 模式
gRPC 中的同步 RPC 模式提供阻塞式 API,调用线程会阻塞直到操作完成,适合需要清晰、可预测控制流而不想管理回调或 Future 的场景。
核心同步架构
同步实现构建在分层架构之上:高层阻塞接口封装底层异步原语,内部通过带 Pluck 操作的 CompletionQueue 将异步事件转为阻塞等待,从而在应用层呈现同步语义,底层仍保持异步。
一元 RPC 模式
单请求、单响应。客户端创建 ClientContext、准备请求、调用 stub 方法(阻塞直到完成);服务端重写服务方法,处理请求并返回 Status。
客户端示例:
cpp
ClientContext context;
HelloRequest request;
request.set_name(user);
HelloReply reply;
Status status = stub_->SayHello(&context, request, &reply);
服务端示例:
cpp
Status SayHello(ServerContext* context, const HelloRequest* request,
HelloReply* reply) override {
std::string prefix("Hello ");
reply->set_message(prefix + request->name());
return Status::OK;
}
当 RPC 延迟可预测且可接受时,同步一元是最佳选择;高吞吐或延迟敏感场景建议异步模式。来源:examples/cpp/helloworld/
服务端流式模式
单请求、多响应(服务端→客户端)。客户端使用 ClientReader<R>,循环 Read() 直到返回 false,最后 Finish() 取状态;服务端使用 ServerWriter<W> 多次 Write(),返回时流结束。
cpp
std::unique_ptr<ClientReader<Feature>> reader(stub_->ListFeatures(&context, rect));
while (reader->Read(&feature)) { /* 处理 */ }
Status status = reader->Finish();
适用:分页数据、实时更新、时间序列。来源:examples/cpp/route_guide/
客户端流式模式
多请求、单响应(客户端→服务端)。客户端使用 ClientWriter<W> 多次 Write(),WritesDone() 后 Finish() 取响应;服务端使用 ServerReader<R> 循环 Read(),最后填充响应并返回 Status。适用:批量上传、批处理。来源:examples/cpp/route_guide/
双向流式模式
全双工,双方可同时发多条消息。客户端/服务端使用 ClientReaderWriter<W,R> / ServerReaderWriter<W,R>,读写可交错或并发(如写线程 + 读循环),WritesDone() 表示客户端写完,Finish() 取最终状态。适用:聊天、实时协作。来源:examples/cpp/route_guide/
同步接口层次结构
- ReaderInterface:NextMessageSize()、Read()(阻塞,流结束返回 false)
- WriterInterface:Write()、WriteLast()
- 客户端:ClientReader(服务端流)、ClientWriter(客户端流)、ClientReaderWriter<W,R>(双向);均提供 Finish()
- 服务端:ServerReader、ServerWriter、ServerReaderWriter<W,R>;ServerStreamingInterface 提供 SendInitialMetadata()
来源:include/grpcpp/support/sync_stream.h
线程安全与完成队列
同一流上 Write()/WritesDone() 与 Read() 可来自不同线程(线程安全);同一流上不可并发调用多个 Read()。同步 API 内部使用「可提取」CompletionQueue,Pluck() 阻塞直到指定操作完成。双向流常用单独线程做读/写以提升吞吐。
同步模式对比
| 模式 | 客户端发送 | 客户端接收 | 用例 | 复杂度 |
|---|---|---|---|---|
| 一元 | 1 | 1 | 简单请求-响应 | 低 |
| 服务端流式 | 1 | N | 分页、实时更新、数据流 | 中 |
| 客户端流式 | N | 1 | 批量上传、批处理 | 中 |
| 双向流式 | N | N | 聊天、协作、连续交换 | 高 |
错误均通过 Status 传达;流式模式中 Read()/Write() 返回 false 可能表示错误,Finish() 始终返回最终状态。元数据通过 ClientContext/ServerContext 管理。
专用流式类型
- ServerUnaryStreamer:客户端为一元,服务端按流处理,须恰好 1 次 Read() 和 1 次 Write()。
- ServerSplitStreamer:客户端为服务端流式,服务端按双向流处理,须 1 次 Read() 后任意次 Write()。
来源:include/grpcpp/support/sync_stream.h
先决条件与从异步迁移
需要:Channel 创建、ServerBuilder 配置、Protocol Buffer 生成代码、sync.h 同步原语。从异步迁移时注意:同步为顺序阻塞,异步为回调/Future;同步占线程,异步多路复用;错误同步直接返回 Status,异步通过回调/Future;流结束同步用 Read() 返回 false,异步用完成回调。中等并发下同步的简单性常优于异步的性能收益。
来源:examples/cpp/helloworld/greeter_client.cc, greeter_server.cc
异步 RPC 模式
gRPC 提供非阻塞通信,C++ 中有两种主要异步 API:Completion Queue (CQ) API 与 Callback API。
架构概述
- CQ API:通过 void* 标签启动操作,用 Next()/Pluck() 轮询完成事件;对调度有细粒度控制。
- Callback API:基于 lambda 与 Reactor,无需标签与轮询,流式用专门的 reactor 类管理。
来源:doc/core/grpc-cq.md, include/grpcpp/support/server_callback.h
Completion Queue 模式
CQ 作为运行时与应用间的同步点。客户端 :创建 CompletionQueue → 用 Async 方法启动 RPC(如 stub_->AsyncSayHello(..., &cq))→ 调用 rpc->Finish(&reply, &status, (void*)tag) → cq.Next(&got_tag, &ok) 阻塞直到完成。每个并发操作需唯一标签。服务端:每个请求封装在 CallData 中,状态机 CREATE → PROCESS → FINISH;主循环从 CQ 取事件,按标签分发到对应 CallData,其 Proceed() 推进状态并在完成时自销毁。来源:examples/cpp/helloworld/greeter_async_client.cc, greeter_async_server.cc
Callback API 模式
一元 :stub_->async()->SayHello(&context, &request, &reply, [](Status s) { ... }); 完成时执行 lambda。服务端一元 :继承 CallbackService,返回 ServerUnaryReactor,调用 context->DefaultReactor() 与 reactor->Finish(Status::OK)。
流式:
- 服务端流式:ServerWriteReactor,OnWriteDone() 中调度下一次 StartWrite(),全部写完调用 Finish()。
- 客户端流式:ClientReadReactor,OnReadDone(bool ok) 中若 ok 则 StartRead() 取下一条;ClientWriteReactor 用 AddHold()/RemoveHold() 防止 OnDone() 在服务器响应前触发。
- 双向流式:ClientBidiReactor / ServerBidiReactor,同时 StartRead/StartWrite,OnReadDone/OnWriteDone 分别驱动两个方向。
来源:examples/cpp/helloworld/greeter_callback_client.cc, route_guide_callback_*
比较与选择
| 方面 | CQ API | Callback API |
|---|---|---|
| 复杂度 | 需手动状态与标签 | 样板少,现代 C++ |
| 并发 | 自管工作线程 | 框架线程池 |
| 控制 | 轮询时机可细调 | 回调隐式流控 |
| 适用 | 传统库、自定义调度 | 新项目、标准异步 |
CQ 的 Next()/Pluck() 线程安全;Callback 下同一 reactor 的回调串行执行。错误:CQ 看 Next() 的 ok 与 status;Callback 用 OnCancel() 处理取消、OnDone(Status) 处理完成与错误。高吞吐可批处理小 RPC 为流式、或使用双向流。来源:doc/core/grpc-cq.md, examples/cpp/
流式语义
gRPC 流式在单次 RPC 中传输消息序列,四种模式在 .proto 中通过 stream 关键字定义;RouteGuide 示例涵盖全部四种。
流式模式与 HTTP/2
- 一元:单请求单响应,基准模式。
- 服务端流式:单请求、多响应(服务器→客户端);适合大结果集、分页、实时更新。
- 客户端流式:多请求、单响应(客户端→服务器);适合批处理、增量上传(如 RecordRoute)。
- 双向流式:两个独立 HTTP/2 流,双方可同时发消息;适合聊天、实时协作(如 RouteChat)。
每条消息为 Length-Prefixed-Message:1 字节压缩标志 + 4 字节长度(大端)+ 有效载荷。DATA 帧边界与消息边界无必然对应,单条消息可跨多 DATA 帧,单 DATA 帧可含多条消息,解析须按长度前缀重组。请求 EOS:最终 DATA 帧设 END_STREAM,无数据时可发空 DATA+END_STREAM。响应 EOS:携带 Trailers 的 HEADERS 帧设 END_STREAM,Trailers 含 grpc-status 等。
来源:doc/PROTOCOL-HTTP2.md, route_guide.proto
流控与背压
HTTP/2 在连接级与流级做基于窗口的流控;窗口耗尽时发送方需等待 WINDOW_UPDATE。gRPC 将背压通过语言 API 暴露:同步 API 上 Write() 会阻塞,reactor API 上 OnWriteDone() 再发起下一次写入。应尊重背压、勿用额外线程绕过流控,否则易导致内存耗尽与连接不稳定。
来源:client_flow_control_client.cc, server_flow_control_server.cc
行为与错误
| 特征 | 一元 | 服务端流式 | 客户端流式 | 双向流式 |
|---|---|---|---|---|
| 请求/响应消息数 | 1/1 | 1/N | N/1 | N/N |
| HTTP/2 流 | 1 | 1 | 1 | 2 |
| 背压方向 | 简单 | 客户端→服务器 | 服务器→客户端 | 双向 |
流中错误:服务器通过带 grpc-status/grpc-message 的 Trailers + END_STREAM 通知;协议错误可用 RST_STREAM 立即终止。取消:客户端可发 END_STREAM 或 RST_STREAM(CANCEL);服务器应释放资源。性能:可调窗口大小、消息粒度;多流共享连接时注意连接级流控与队头阻塞。来源:doc/PROTOCOL-HTTP2.md
负载均衡架构
gRPC 在每次调用级别做负载均衡(非连接级),即使单客户端也可将请求分发到多后端。系统位于名称解析与传输连接之间,根据策略与连接状态决定每个 RPC 由哪个后端处理。
核心组件
- 通道:管理到后端的连接,内含解析器、负载均衡策略、子通道。
- 子通道:到单个后端地址的连接;由 LB 策略创建与管理,经 SubchannelInterface 暴露。
- 解析器:将服务器 URI 转为地址列表 + 服务配置(含 LB 策略名、通道参数)。
- 负载均衡策略 :接收解析结果,创建/管理子通道,聚合连接状态,每次调用通过 SubchannelPicker 选子通道。
来源:load-balancing.md, lb_policy.h, subchannel.h
策略架构与 Pick 结果
LoadBalancingPolicy 分离控制平面 (解析器更新、子通道生命周期、状态监控、UpdateState)与数据平面 (SubchannelPicker::Pick())。控制平面经 work serializer 序列化;Pick() 返回 PickResult :Complete (选定子通道)、Queue (排队等新选择器)、Fail (带状态失败,可区分等待就绪与否)、Drop(主动丢弃、不重试,用于限流/熔断)。
来源:lb_policy.h
策略注册与分层
LoadBalancingPolicyRegistry 在初始化时注册策略名→工厂;服务配置可指定策略(如 round_robin、grpclb)。ChildPolicyHandler 支持分层:父策略将地址委托给子策略,子策略做实际选子通道逻辑,父策略再在子策略间做高层选择(如按位置、权重)。
子通道管理
Subchannel 维护到单后端的连接、退避重连、与 I/O 轮询集成。通过 ConnectivityStateWatcherInterface 向策略报告 READY/TRANSIENT_FAILURE/IDLE 等。子通道由 ChannelControlHelper::CreateSubchannel() 创建,通道侧可有池化复用。TRANSIENT_FAILURE 视为持续到重新连接成功为止。
内置策略与工作流
| 策略 | 选择策略 | 用例 |
|---|---|---|
| pick_first | 选第一个可达地址,带退避 | 单后端、简单部署 |
| round_robin | 轮询就绪子通道,失败自动重连 | 多后端负载分配 |
| grpclb | 委托外部均衡器(已趋 xDS 替代) | 集中管理 |
默认无配置时为 pick_first。工作流:名称解析 → 策略实例化 → 子通道创建 → 状态聚合 → 每 RPC 调用当前选择器 Pick()。实现自定义策略时:带 Locked 的方法须在工作序列化器中调用;Pick() 路径尽量轻量;用 CallState::Alloc() 做每调用分配;需触发重连时可用 QueuePicker + ExitIdleLocked()。xDS 集成在相同 LB 抽象上构建分层策略(优先级、加权目标、异常检测等)。来源:load-balancing.md, client_channel.h
轮询策略 (Round Robin)
轮询是调用级 客户端负载均衡策略,按顺序将 RPC 分发到多个后端,实现流量均匀分配。实现从随机起始索引开始,避免多客户端同时从索引 0 带来的「惊群」问题。
架构与选择算法
RoundRobin 扩展 LoadBalancingPolicy,维护 endpoint_list_ (当前活动列表)与 latest_pending_endpoint_list_(待替换列表),实现地址更新时的平滑过渡。每个端点可包含多个子通道(如 IPv4/IPv6)。Picker 用原子递增取下一个索引并委托给对应子通道选择器:
cpp
size_t index = last_picked_index_.fetch_add(1, std::memory_order_relaxed) % pickers_.size();
return pickers_[index]->Pick(args);
无锁设计保证高并发下线程安全。来源:round_robin.cc
状态聚合与地址更新
整体状态优先级:有任一 READY → READY;否则有 CONNECTING/IDLE → CONNECTING;否则有 IDLE → IDLE;全部 TRANSIENT_FAILURE → TRANSIENT_FAILURE。IDLE 与 CONNECTING 等同处理以快速恢复。策略维护 num_ready_、num_connecting_、num_transient_failure_ 等计数。地址更新:解析器送新列表 → 建待处理列表 → 待处理有 READY 或全部 TF 时再交换为活动,避免空列表期间丢流量。退避与重连遵循通道退避配置;ResetBackoffLocked() 可重置退避。
配置与用例
服务配置示例:"loadBalancingConfig": [{ "round_robin": {} }]。适用:无状态服务、同构后端、开发/测试;不适用:异构容量、地理感知路由。优势:确定性分布、无锁选择、快速故障转移;局限:无加权、无延迟感知、维护所有后端连接。与 Pick First、Weighted RR、Priority 等对比见 load-balancing.md。来源:load-balancing.md, round_robin_test.cc
Pick First 策略
Pick First 是 gRPC 默认 负载均衡策略:与一个后端建立单一持久连接,所有 RPC 经该连接路由直至连接失败,优先连接稳定性与简单性。
核心架构与 Happy Eyeballs
策略从解析器接收地址列表,按顺序 尝试连接;一旦某地址连接成功,即选定该子通道并丢弃 SubchannelList,后续 RPC 全部走该子通道。组件:Pick First 策略、SubchannelList(多地址连接尝试)、SubchannelData(每后端状态)。实现 RFC-8305 Happy Eyeballs :地址按族(IPv4/IPv6)交错、顺序尝试(默认间隔 250ms,可配置 100--2000ms),某地址 TRANSIENT_FAILURE 后立即试下一个;若所有地址都至少失败一次,则转为并行连接所有子通道以加快重连。来源:pick_first.cc
状态与配置
状态:IDLE → CONNECTING(ExitIdle 或解析器更新)→ READY(任一子通道 READY 即选定)→ READY 期间若选定子通道断开则回 IDLE 或(实验 pick_first_ready_to_connecting)保持 CONNECTING 并启动新 Happy Eyeballs。配置:shuffleAddressList(连接前随机打乱地址,防羊群);GRPC_ARG_HAPPY_EYEBALLS_CONNECTION_ATTEMPT_DELAY_MS(100--2000,默认 250);可选健康检查、状态消息前缀等。指标:connection_attempts_succeeded、connection_attempts_failed、disconnections。与 Round Robin 对比:Pick First 单连接、无负载分散、适合有状态/单后端;Round Robin 多连接、均匀分布、适合无状态。来源:load-balancing.md, pick_first.h
高级负载均衡策略
高级策略在可组合架构上构建:父策略可委托子策略,ChildPolicyHandler 支持平滑策略切换与生命周期管理;控制平面管理地址与连接状态,数据平面通过 SubchannelPicker 做每 RPC 路由。
环形哈希 (Ring Hash)
一致性哈希,最小化增删后端时的重映射,适合有状态/缓存。每后端在环上有多虚拟节点;按请求派生键(如 requestHashHeader 或 RPC 路径)哈希选后端。配置:minRingSize、maxRingSize(默认 1024--8388608),ring_size = min(maxRingSize, max(minRingSize, num_backends*100))。requestHashHeader 为实验性。来源:ring_hash.cc
加权与优先级
- 加权轮询 (WRR):每后端权重,流量比例近似权重;零权重不接流量;静态步长调度,O(1) 选择。
- 加权目标 (Weighted Target):在 locality 级加权,每 target 内用子策略(如 round_robin);适合多区域按容量/优先级分流。
- 优先级 (Priority):多层级,流量只到最高优先级且就绪的层级;某层全 TRANSIENT_FAILURE 则故障转移到下一层;无 overprovisioning,依赖 xDS 控制面更新。来源:weighted_round_robin.cc, weighted_target.cc, priority.cc
异常值检测 (Outlier Detection)
包装子策略,收集子通道指标并剔除异常后端。成功率剔除 :成功率低于(平均值 - 标准差×因子)则剔除;失败百分比剔除:失败率超阈值则剔除;均需最少请求数。有最大剔除百分比、最小剔除时长等保护。来源:outlier_detection.cc
组合与 xDS
组合示例:Priority → 多 Locality(Weighted Target) → 各层内 Round Robin/WRR/Pick First;或 Outlier Detection → Ring Hash。xDS 提供动态配置、优先级 locality、Ring Hash、Least Request、Outlier Detection、自定义策略等(见 gRFC A27/A48/A50/A52/A64)。配置更新采用"先建后断":新子策略 READY 后替换旧策略。来源:child_policy_handler.h, grpc_xds_features.md
加权和优先级负载均衡
加权轮询 :每后端配置权重,流量比例近似权重,零权重不接流量;加权目标 :在 locality 级配置权重,每 target 内用子策略(round_robin 等);优先级 :多层级,仅最高优先级且就绪的层级接流量,全 TRANSIENT_FAILURE 则故障转移到下一层。详见上文 高级负载均衡策略 与 doc/load-balancing.md。
名称解析概述
名称解析将服务目标 (URI)转为端点地址与服务配置,是客户端通道的基础层;支持 DNS、服务发现、Unix 套接字、自定义命名,通过可插拔解析器实现。
核心组件
- Resolver :StartLocked()、RequestReresolutionLocked()、ResetBackoffLocked()、ShutdownLocked()。Result 含:EndpointAddressesList(地址列表)、ServiceConfig、resolution_note、ChannelArgs、result_health_callback(LB 拒绝更新时解析器可退避)。
- ResolverFactory:scheme()、IsValidUri()、CreateResolver();与 URI scheme 绑定。
- ResolverRegistry :按 scheme 选工厂;未指定 scheme 时默认 dns:// ,如
example.com:8080→dns:///example.com:8080。
地址用 EndpointAddresses 表示(grpc_resolved_address 列表 + ChannelArgs);单端点可含多地址(如 IPv4/IPv6)。来源:resolver.h, resolver_factory.h, endpoint_addresses.h
URI Schemes 与解析流程
| Scheme | 格式/用途 |
|---|---|
| dns | dns:[//authority/]host[:port],默认 443/80 |
| unix | unix:path,本地 IPC |
| unix-abstract | Linux 抽象命名空间 |
| vsock | vsock:cid:port(VM) |
| ipv4/ipv6 | 字面量地址(C-core) |
流程:创建通道 → 解析目标 → 按 scheme 查工厂 → 创建 Resolver → StartLocked();拉取 (如 DNS)由 PollingResolver 管理冷却与退避,RequestReresolutionLocked() 触发查询;推送(服务发现)订阅更新,有变更即 ReportResult()。result_health_callback 使 LB 可反馈是否接受更新,解析器据此退避。内置实现:DNS、xDS、sockaddr、fake。来源:doc/naming.md, client_channel.h
DNS 解析器实现
DNS 解析器将服务名(dns URI)转为可连接地址,Result 含 addresses、service_config、resolution_note、args、result_health_callback。
实现与配置
- 原生解析器 (native):基于 PollingResolver,用 I/O 管理器 LookupHostname() 异步查询;GRPC_ARG_DNS_MIN_TIME_BETWEEN_RESOLUTIONS_MS 默认 30s 冷却;退避 1s 起、乘数 1.6、最大 120s、20% 抖动。
- c-ares:可选,用于自定义 DNS 服务器、DoT 等;通过环境变量选择。
- Event Engine 解析器:基于事件引擎,与 iomgr 解耦。
状态机:Shutdown、Resolving、Waiting、Result Callback Pending。Request 合并与冷却避免重复查询;result_health_callback 使 LB 拒绝时解析器退避。dns_resolver_trace 可开启详细日志。来源:resolver/dns/native/, polling_resolver.h
自定义解析器插件
自定义解析器需实现:Resolver 子类(StartLocked、RequestReresolutionLocked、ResetBackoffLocked、ShutdownLocked,通过 ResultHandler::ReportResult 返回 Result)、ResolverFactory 子类(scheme()、IsValidUri()、CreateResolver()),并在初始化时将工厂注册到 ResolverRegistry。Result 含 EndpointAddressesList、ServiceConfig、resolution_note、ChannelArgs、result_health_callback。可经 GRPC_ARG_* 传配置;地址可带 GRPC_ARG_ADDRESS_NAME 等属性供 LB 使用。用于 etcd、Consul 等私有服务发现。参见 doc/naming.md、src/core/resolver/。
服务端身份验证
服务端在 RPC 到达业务逻辑前通过身份验证拦截器 校验客户端身份,并用 AuthContext 作为唯一事实来源做授权决策;勿依赖其他可被客户端篡改的上下文做认证。
AuthContext 与 API
AuthContext 是连接级对象,封装对端身份与安全机制,可视为多值映射。常用:IsPeerAuthenticated()、GetPeerIdentity()、GetPeerIdentityPropertyName()、FindPropertyValues(name)。属性包括:transport_security_type(如 "ssl")、x509_common_name、x509_pem_cert、x509_subject_alternative_name(可多条)等。mTLS 时对端身份通常由 SAN 或 CN 表示。来源:include/grpcpp/security/auth_context.h
拦截器与 SSL 配置
内置:TLS/SSL 证书验证(使用 SSL 凭据时自动);自定义通过 AuthMetadataProcessor :Process(auth_metadata, context, consumed_auth_metadata, response_metadata),返回非 OK 即中止 RPC。服务端 SSL 选项:SslServerCredentialsOptions(pem_root_certs、pem_key_cert_pairs、client_certificate_request)。客户端证书请求 :DONT_REQUEST、REQUEST_BUT_DONT_VERIFY、REQUEST_AND_VERIFY、REQUIRE_BUT_DONT_VERIFY、REQUEST_AND_REQUIRE_AND_VERIFY(标准 mTLS)。服务方法内通过 context->auth_context() 取 AuthContext,检查 IsPeerAuthenticated() 与 GetPeerIdentity() 做授权。模式:匿名、仅 TLS 加密、mTLS、自定义令牌。注意:AuthContext 为连接级,修改会影响同连接后续调用;CallCredentials 仅在连接安全级别满足时有效。来源:doc/server_side_auth.md, examples/cpp/auth/ssl_server.cc
TLS/SSL 配置
gRPC 通过 ChannelCredentials 、ServerCredentials 、CallCredentials 分层抽象 TLS/SSL;可组合(如 TLS + CallCredentials)。
基础 SSL
客户端 :SslCredentialsOptions(pem_root_certs、可选 pem_private_key/pem_cert_chain 用于 mTLS);空 pem_root_certs 时用系统默认根,生产建议显式指定。服务端:SslServerCredentialsOptions(pem_key_cert_pairs、pem_root_certs、client_certificate_request);client_certificate_request 从 DONT_REQUEST 到 REQUEST_AND_REQUIRE_AND_VERIFY 控制 mTLS。来源:credentials.h, server_credentials.h
实验性 TLS API
TlsChannelCredentialsOptions / TlsServerCredentialsOptions:CertificateProvider (StaticDataCertificateProvider 内存证书、FileWatcherCertificateProvider 文件轮换);watch_root_certs()、set_certificate_verifier()、set_min/max_tls_version()(默认 TLS 1.2--1.3);可选 CRL。自定义验证器 :继承 ExternalCertificateVerifier,实现 Verify()(可访问 peer_cert、dns_names、common_name 等),Cancel()。服务端通过 context->auth_context() 取对端身份。组合:CompositeChannelCredentials(ssl_creds, call_creds) 实现 TLS + 每次调用令牌等。来源:tls_credentials_options.h, tls_certificate_provider.h, examples/cpp/auth/
凭证类型和提供者
ChannelCredentials :建立安全通道(如 SslCredentials、TlsCredentials、InsecureChannelCredentials);ServerCredentials :服务端端口(SslServerCredentials、TlsServerCredentials、InsecureServerCredentials);CallCredentials:每次调用附加认证(如 AccessTokenCredentials、GoogleDefaultCredentials)。可组合:CompositeChannelCredentials(channel_creds, call_creds) 实现 TLS + 令牌。各语言 API 提供对应工厂;C-core 实现见 grpc_security。参见 doc/security.md、credentials.h。
mTLS 和证书管理
双向 TLS :客户端与服务端均出示证书,服务端 client_certificate_request 设为 REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY;客户端 SslCredentialsOptions 提供 pem_private_key、pem_cert_chain。动态证书 :实验性 API 中 CertificateProvider(StaticDataCertificateProvider、FileWatcherCertificateProvider)支持证书轮换而无须重建通道;FileWatcher 需原子更新(目录重命名或符号链接)。根 CA 与身份证书可分别 watch;证书验证器、TLS 版本、CRL 等见 TLS/SSL 配置。xDS 等控制面可下发证书或 CA。参见 doc/security.md、src/core/tsi/、tls_certificate_provider.h。
指标和统计
gRPC 遥测基于分层架构:插桩 (Counter、Histogram、Gauge)通过 StatsPlugin 接口导出,可与 OpenTelemetry、Prometheus 等集成。
插桩类型与域
- Counter:仅增(请求数、错误数);RegisterUInt64Counter/RegisterDoubleCounter。
- Histogram:值分布(延迟、消息大小);线性/指数桶,BucketInBoundsFor 二分查找。
- Gauge:瞬时值(连接数、内存);通过 GaugeProvider 回调按需计算。
Instrument Domain:继承 InstrumentDomain,定义 Backend(LowContentionBackend / HighContentionBackend)、kLabels、RegisterCounter/RegisterHistogram。收集范围形成 DAG:根→全局→每通道/每服务器叶范围;创建存储时用最特定范围。来源:src/core/telemetry/
Channelz 与调用跟踪
Channelz :内置实时监控,protobuf API;实体类型:kTopLevelChannel、kSubchannel、kServer、kSocket、kListenSocket;指标含连接状态、调用计数、退避、流控等。ChannelTrace 记录事件,内存限制可配置(如 GRPC_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE)。CallTracer:CallTracerInterface → ClientCallTracer/ServerCallTracer,捕获每 RPC 元数据、消息大小、耗时、状态码;支持 Annotation(键值对)。StatsAsJson 导出 JSON。OpenTelemetry:StatsPlugin 集成、examples/otel 与 CSM 示例。最佳实践:一致标签(grpc.target、grpc.method)、低基数、按并发选 Backend。来源:channelz.h, call_tracer.h, examples/otel
调用追踪和日志记录
分布式追踪 :trace ID、span 可通过元数据(如 grpc-trace-bin)传递;与 OpenTelemetry 、OpenCensus 集成,CallTracer 提供每 RPC 注释与耗时。日志 :服务端/客户端可记录请求与响应、状态码、错误信息;与各语言日志框架结合。指标与 Channelz 见 指标和统计。参见 doc/grpc-auth-support.md、call_tracer.h、各语言 tracing 文档。