gRPC完整文档

gRPC 概述与入门

本文档来自 zread.ai 对 grpc/grpc 仓库的解析,合并了该站所有子页面内容。来源:https://zread.ai/grpc/grpc

目录

  1. 概述
  2. [为什么选择 gRPC?](#为什么选择 gRPC?)
  3. 核心架构
  4. [gRPC 如何工作](#gRPC 如何工作)
  5. 流式传输能力
  6. 支持的语言
  7. 项目结构
  8. 关键特性概览
  9. [何时使用 gRPC](#何时使用 gRPC)
  10. 下一步
  11. 社区和生态系统
  12. 快速入门
  13. [构建和安装 gRPC](#构建和安装 gRPC)、特定语言设置指南、[Hello World 示例](#Hello World 示例)
  14. 最新更新和发布计划安全审计发现和修复社区反馈和问题
  15. [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 开发流程遵循四个基本步骤:

  1. 定义服务 :使用 Protocol Buffers IDL 创建 .proto 文件,包含服务定义、RPC 方法和消息类型。例如,一个简单的问候服务可能定义接受 HelloRequest 并返回 HelloReplySayHello 方法。
  2. 生成代码 :带有 gRPC 插件的 Protocol Buffer 编译器(protoc)自动生成特定语言的代码,包括用于发起 RPC 调用的客户端存根和用于实现服务方法的服务器接口。
  3. 实现服务器:为每个 RPC 方法编写实际业务逻辑,实现生成的服务器接口;服务器监听网络地址并处理传入请求。
  4. 创建客户端:创建 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


下一步

推荐学习路径:

  1. 快速开始 --- 用喜欢的语言在几分钟内运行基本 gRPC 服务端与客户端
  2. 构建和安装 gRPC --- 按详细构建说明配置开发环境
  3. 特定语言设置指南 --- 深入了解所选语言的设置
  4. Hello World 示例 --- 通过示例理解核心概念
  5. gRPC 概念和架构 --- 深入理解架构与设计原则

对协议内部细节感兴趣可阅读 gRPC 协议规范摘要HTTP/2 实现细节

来源:README.md, BUILDING.md


社区和生态系统

gRPC 拥有活跃的开源社区,定期发布、全面文档和丰富工具支持;项目遵循语义化版本,约每六周进行小版本发布,并按需发布补丁。

关键资源:


快速入门

几分钟内快速上手 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

来源:BUILDING.md, BUILDING.md

其他语言安装
语言 安装方法 命令
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 并返回 HelloReplysyntax = "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 installrake

来源: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 示例构建和安装 gRPCgRPC 概念和架构。详细示例见官方 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_channelasync/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::RpcServeradd_http2_porthandle(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 开放 所有

安全最佳实践

  1. 避免多线程进程中 fork :必要时 export GRPC_ENABLE_FORK_SUPPORT=0,或使用进程生成。
  2. Keepalive 间隔:在 #32912 修复前,应用层强制执行 ≥10 秒(gRFC A8)。
  3. 监控线程池:对 gRPC 相关线程数设告警,防止无界增长。
  4. 固定稳定版本:macOS/iOS 可考虑固定到已验证稳定版本。
  5. 安全报告:勿公开开 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 IDLHello World ExamplesAbstract gRPC Protocol SpecificationHTTP/2 Implementation DetailsClient 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_librarycc_proto_librarycc_grpc_library(grpc_only=True)。Python:py_proto_librarypy_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) APICallback 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() 返回 PickResultComplete (选定子通道)、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:8080dns:///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 通过 ChannelCredentialsServerCredentialsCallCredentials 分层抽象 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 文档。

相关推荐
Highcharts.js7 小时前
如何设置自定义Highcharts导出服务器?
服务器·highcharts·自定义导出·导出服务器·导出模块·渲染功能
江湖有缘7 小时前
基于华为openEuler系统部署Gitblit服务器
运维·服务器·华为
yuanmenghao7 小时前
Linux 性能实战 | 第 10 篇 CPU 缓存与内存访问延迟
linux·服务器·缓存·性能优化·自动驾驶·unix
QT.qtqtqtqtqt8 小时前
SQL注入漏洞
java·服务器·sql·安全
..过云雨8 小时前
多路转接select系统调用详解
网络·网络协议·tcp/ip
qq_5470261798 小时前
LangChain 1.0 核心概念
运维·服务器·langchain
Mr_Xuhhh8 小时前
介绍一下ref
开发语言·c++·算法
王老师青少年编程8 小时前
2024年信奥赛C++提高组csp-s初赛真题及答案解析(完善程序第2题)
c++·题解·真题·初赛·信奥赛·csp-s·提高组
Trouvaille ~8 小时前
【Linux】进程间关系与守护进程详解:从进程组到作业控制到守护进程实现
linux·c++·操作系统·守护进程·作业·会话·进程组