gRPC从0到1系列【1】
文章目录
- 一、gRPC概述
- 1.1 文档资料
- 1.2 概述
- 1.3 优缺点
- 1.4 典型应用场景
- 1.5 gRPC的组成部分
- 1.5.1 接口契约层 - Protocol Buffers
- 1.5.2 服务定义(Service Definition)
- 1.5.3 代码生成器(protoc + gRPC 插件)
- 1.5.4 传输层:HTTP/2
- 1.5.5 客户端与服务端运行时(Runtime)
- 1.5.6 扩展机制:拦截器(Interceptors)与元数据(Metadata)
- 1.6 gRPC组件关系
- 1.7 总结表格
- 1.8 原理流程图
一、gRPC概述
1.1 文档资料
- 官网
https://grpc.io/
- 中文站
https://grpc.org.cn/
1.2 概述
在 gRPC 出现之前,微服务架构内部的服务通信主要依赖于基于文本的协议,如 RESTful API(使用 JSON/XML over HTTP)。虽然 REST 简单、通用,但在高性能、强类型、多语言环境下的微服务通信中,逐渐暴露出一些局限性:
- 效率问题:JSON/XML 是文本格式,序列化/反序列化效率较低,且报文体积较大。
- 弱类型约束:JSON 没有严格的模式(Schema),接口的请求和响应格式需要依赖额外的文档来约定,容易出错,且难以在编译期进行类型检查。
- 复杂的接口管理:随着接口增多和版本迭代,维护和同步 API 文档变得困难。
- 有限的通信模式:传统的 HTTP/1.1 + REST 主要支持请求-响应模式,难以直接支持流式数据传输等更复杂的交互模式。
gRPC 由 Google 开发并开源,它基于其内部大规模使用的 Stubby 框架的理念。Google 为了应对上述挑战,并充分利用现代网络协议(如 HTTP/2)的优势,创造了 gRPC。
gRPC 是一个现代开源的高性能远程过程调用 (RPC) 框架,可以在任何环境中运行。它可以高效地连接数据中心内部和跨数据中心的服务,并为负载均衡、跟踪、健康检查和身份验证提供可插拔的支持。它也适用于分布式计算的最后一英里,将设备、移动应用程序和浏览器连接到后端服务。
工作原理:
1.3 优缺点
优点
优势维度 | 具体说明 |
---|---|
高性能 | 二进制序列化(Protobuf)+ HTTP/2 多路复用,比 JSON+HTTP/1.1 吞吐量提升 2-3 倍,延迟显著降低。 |
跨语言兼容 | 基于 Protobuf IDL 生成多语言代码,彻底解决不同语言服务间的接口对齐问题(如 Go 调用 Java 服务无需手动解析数据)。 |
强类型接口 | Protobuf 定义接口时强制指定字段类型(如 int32、string、message),编译期即可检查类型错误,避免运行时数据格式异常。 |
多通信模式 | 支持 4 种通信模式(简单 RPC、服务端流、客户端流、双向流),灵活应对实时数据传输、批量处理等场景。 |
云原生友好 | 轻量、低资源占用,完美适配 Kubernetes 容器编排,且与 Istio(服务网格)深度集成,支持流量控制、灰度发布。 |
缺点
劣势维度 | 具体说明 |
---|---|
学习成本较高 | 需掌握 Protobuf 语法、HTTP/2 原理及 gRPC 特有概念(如流、元数据),相比 RESTful API(JSON+HTTP/1.1)入门门槛更高。 |
浏览器兼容性差 | 基于 HTTP/2 二进制帧,浏览器无法直接发起 gRPC 请求(需通过 gRPC-Web 代理转换为 HTTP/1.1 文本格式),不适合前端直接调用。 |
调试难度较大 | 二进制传输数据无法通过浏览器 F12 或 Wireshark 直接解析,需使用 gRPC 专用工具(如 grpcurl、Postman 新版)调试。 |
生态成熟度低于 REST | RESTful API 有大量成熟工具(如 Swagger、Postman)、文档生成方案和社区支持,gRPC 相关工具链仍在完善中。 |
服务契约变更成本高 | Protobuf 接口兼容性需严格遵守(如新增字段需标记为 optional,删除字段需谨慎),否则可能导致旧客户端崩溃,需做好版本管理。 |
1.4 典型应用场景
gRPC 并非适用于所有场景,以下是其优势最突出的核心场景:
- 微服务内部通信:微服务间(如订单服务调用支付服务、用户服务)需要低延迟、高吞吐的通信,且服务语言多样(如 Go 网关 + Java 业务服务),gRPC 可替代 RESTful API 提升效率。
- 示例:Kubernetes 内部组件(api-server、etcd、kubelet)通过 gRPC 通信。
- 实时数据传输场景:需要持续双向数据交互的场景,如实时聊天、直播弹幕、股票行情推送,gRPC 双向流比 WebSocket 更高效(二进制传输 + HTTP/2 优化)。
- 跨语言数据同步:多语言系统间的批量数据同步(如 Python 数据分析服务向 Java 存储服务批量写入数据),Protobuf 序列化可减少数据体积,客户端流模式支持批量传输。
- 高性能中间件通信:数据库、缓存、消息队列等中间件的客户端 - 服务端通信,如 etcd 的客户端(支持多语言)通过 gRPC 与服务端交互。
- 移动端 / 物联网(IoT)通信:移动端或 IoT 设备(带宽 / 算力有限)与后端服务通信,gRPC 小体积、低延迟的特性可减少设备资源消耗。
不适用于的场景:
- 前端直接调用后端服务(需额外引入 gRPC-Web 代理,复杂度高于 REST);
- 对外公开的 API 服务(用户 / 第三方开发者更熟悉 REST/JSON,调试成本低)。
1.5 gRPC的组成部分
1.5.1 接口契约层 - Protocol Buffers
这是 gRPC 的基石和规范,定义了服务的"是什么"。
- 角色:接口定义语言(IDL)和序列化机制。
- 核心文件:
.proto
文件。 - 定义内容:
- 服务(Service):包含一组远程方法。
- RPC 方法:定义方法名、请求消息类型、响应消息类型以及通信模式(一元、流式等)。
- 消息(Message):定义方法调用中传输的数据结构,是强类型的字段集合。
- 作用:提供唯一的、与编程语言无关的 API 契约,是所有代码生成的基础。
1.5.2 服务定义(Service Definition)
- 在
.proto
文件中通过service
块定义远程可调用的方法。 - 每个方法明确指定:
- 请求消息类型(input)
- 响应消息类型(output)
- 通信模式(Unary、Server Streaming、Client Streaming、Bidirectional Streaming)
1.5.3 代码生成器(protoc + gRPC 插件)
- 使用官方编译器
protoc
配合对应语言的 gRPC 插件(如grpc-java
、grpc-go
)。 - 自动生成:
- 客户端存根(Stub):隐藏网络细节,提供本地方法调用接口。
- 服务端基类/接口(Skeleton):开发者只需实现业务逻辑。
例如:protoc --java_out=. --java-grpc_out=. user.proto 生成 Go 代码。
1.5.4 传输层:HTTP/2
- gRPC 强制依赖 HTTP/2 作为底层传输协议。
- 关键特性支持:
- 多路复用(Multiplexing):多个 RPC 调用共享一个 TCP 连接。
- 二进制帧:高效解析,减少带宽。
- 头部压缩(HPACK):降低元数据开销。
- 流式通信原生支持:天然适配 gRPC 的流式 RPC。
注意:gRPC 不兼容 HTTP/1.1(除非使用 gRPC-Web + 代理)。
1.5.5 客户端与服务端运行时(Runtime)
- 客户端
- 通过 Channel 管理连接。
- 使用 Stub 发起调用(支持同步/异步、阻塞/非阻塞)。
- 服务端
- 绑定端口,监听 gRPC 请求。
- 调度请求到对应的 服务实现类。
- 支持多线程/协程处理并发。
1.5.6 扩展机制:拦截器(Interceptors)与元数据(Metadata)
- 拦截器(Interceptors)
- 类似中间件,可在请求/响应前后插入逻辑。
- 常用于:认证、日志、监控、重试、限流。
- 支持客户端和服务端。
- 元数据(Metadata)
- 传递非业务上下文信息(如 token、trace ID、user-agent)。
- 以 key-value 形式附加在 RPC 调用中(类似 HTTP headers)。
1.6 gRPC组件关系
1.7 总结表格
组件 | 功能 | 关键技术 |
---|---|---|
Protocol Buffers | 接口定义 + 序列化 | .proto 文件、二进制编码 |
服务定义 | 声明 RPC 方法 | Unary / Streaming |
代码生成器 | 自动生成客户端/服务端代码 | protoc + 语言插件 |
HTTP/2 | 高性能传输层 | 多路复用、二进制帧、头部压缩 |
客户端/服务端运行时 | 执行 RPC 调用与处理 | Stub、Channel、服务实现 |
拦截器 & 元数据 | 扩展与上下文传递 | 中间件、headers-like 机制 |