2. gRPC 基础入门

在深入微服务链路的重试与错误处理之前,必须先理解 gRPC 的核心概念。gRPC 是现代微服务架构中最高效的远程过程调用(RPC)框架之一,它基于 HTTP/2 协议,并使用 Protocol Buffers(protobuf)作为接口定义语言(IDL)与序列化工具。本章将帮助你建立对 gRPC 的完整认知,为后续配置重试机制打下坚实基础。

2.1 gRPC 定义

gRPC 是由 Google 开源的高性能、跨语言的 RPC 框架。它允许客户端应用像调用本地方法一样直接调用另一台机器上的服务端方法,屏蔽了网络通信、序列化、连接管理等底层细节。

核心特性:gRPC 默认使用 Protocol Buffers 进行数据序列化,基于 HTTP/2 进行传输,支持双向流、流控、头部压缩等高级特性。

2.2 Protocol Buffers 简介

Protocol Buffers(简称 protobuf)是一种语言无关、平台无关、可扩展的序列化结构数据格式。与 JSON 或 XML 相比,protobuf 更小、更快、更简单。开发者通过编写 .proto 文件定义服务接口和消息结构,然后使用 protoc 编译器生成目标语言的代码。

以下是一个典型的 .proto 文件示例,定义了一个订单服务:

syntax = "proto3";

package order;

// 定义订单服务
service OrderService {
  rpc CreateOrder (CreateOrderRequest) returns (CreateOrderResponse);
  rpc GetOrder (GetOrderRequest) returns (GetOrderResponse);
}

// 创建订单请求消息
message CreateOrderRequest {
  string user_id = 1;
  repeated string item_ids = 2;
  double total_amount = 3;
}

// 创建订单响应消息
message CreateOrderResponse {
  string order_id = 1;
  int32 status_code = 2;
  string status_message = 3;
}

// 查询订单请求消息
message GetOrderRequest {
  string order_id = 1;
}

// 查询订单响应消息
message GetOrderResponse {
  string order_id = 1;
  string user_id = 2;
  repeated string item_ids = 3;
  double total_amount = 4;
  string status = 5;
}
提示:protobuf 的字段编号(如 = 1、= 2)是二进制编码的唯一标识,一旦发布不应修改,否则会导致新旧版本兼容性问题。

2.3 gRPC 与 REST 对比

在微服务架构中,REST 和 gRPC 是两种主流的服务间通信方式。下表从多个维度对比两者的差异,帮助你根据场景做出技术选型:

对比维度 gRPC REST
底层协议 HTTP/2(支持多路复用、流控) HTTP/1.1(通常)或 HTTP/2
数据格式 Protocol Buffers(二进制,紧凑高效) JSON / XML(文本,可读性强)
接口定义 强类型,通过 .proto 文件严格定义 松散,通常依赖 OpenAPI / Swagger 文档
通信模式 支持一元、服务端流、客户端流、双向流 主要支持请求-响应(一元模式)
性能 高(二进制序列化 + HTTP/2 头部压缩) 中(文本序列化,数据冗余较大)
浏览器支持 需要 gRPC-Web 代理 原生支持
适用场景 微服务内部通信、低延迟、高吞吐场景 对外 API、Web 前端、开放接口
选型建议:在微服务链路内部,gRPC 是更优的选择;如果服务需要暴露给浏览器或第三方客户端,REST 或 gRPC-Web 更合适。不要在同一链路中混用两种协议,否则会增加错误处理的复杂度。

2.4 gRPC 核心优势

gRPC 之所以成为微服务通信的首选,主要得益于以下核心优势:

  • 高性能序列化:Protocol Buffers 的二进制编码比 JSON 小 3~10 倍,解析速度快 20~100 倍,显著降低网络延迟和 CPU 开销。
  • HTTP/2 多路复用:单个 TCP 连接可同时处理多个请求和响应,避免了 HTTP/1.1 的队头阻塞问题,提升连接利用率。
  • 双向流式通信:支持服务端流、客户端流和双向流,适合实时推送、大数据传输、聊天等场景。
  • 强类型接口契约:.proto 文件定义了严格的接口和消息结构,自动生成客户端和服务端桩代码,减少运行时类型错误。
  • 跨语言互操作性:支持 C++、Java、Go、Python、Node.js 等十余种语言,适合异构微服务架构。
  • 内置负载均衡与重试:gRPC 原生支持客户端负载均衡策略(如轮询、加权),并提供了可配置的重试机制,这正是本课程后续章节的重点。

下图展示了 gRPC 在微服务通信中的典型架构,以及各组件之间的交互关系:

gRPC 微服务通信架构图 gRPC 客户端 (订单服务消费者) Stub(桩代码) HTTP/2 客户端 负载均衡器 重试拦截器 HTTP/2 gRPC 服务端 (订单服务提供者) HTTP/2 服务端 服务实现 拦截器链 错误处理 内部调用 后端服务 (数据库 / 缓存) MySQL Redis

上图清晰地展示了 gRPC 客户端通过 Stub 发起调用,经过 HTTP/2 传输、负载均衡和重试拦截器,最终到达服务端处理并返回响应的完整链路。重试拦截器是后续章节的核心组件,它负责在遇到临时故障时自动重试,提升系统的鲁棒性。

关键理解:gRPC 的重试机制通常实现在客户端拦截器中,与服务端解耦。这意味着即使服务端暂时不可用,客户端也能通过配置合理的重试策略(如指数退避)自动恢复通信,而不需要业务代码手动处理。