第1章:gRPC简介与基础概念——它到底是什么?
1.1 一个真实场景引出的问题
我第一次接触gRPC,其实挺晚的。那时候公司要做微服务改造,服务间调用全用REST接口。你知道的,REST接口传JSON,看着挺友好,但压测一上,问题就来了——序列化慢、带宽占用高、接口文档还得单独维护。
后来我试着引入了gRPC。说实话,第一次部署的时候心里也没底。但用下来之后,我只想说一句话:早该换了。
gRPC,全称是gRPC Remote Procedure Calls。它由谷歌在2015年开源,核心目标就一个:让服务间通信像本地函数调用一样简单、高效、安全。
一句话概括:gRPC是一个高性能、跨语言的远程过程调用(RPC)框架,底层基于HTTP/2,数据序列化使用Protocol Buffers。
说白了,你写好一个proto文件定义接口,然后gRPC自动生成客户端和服务端代码。你只需要关心业务逻辑,不用管底层的网络通信细节。
1.2 gRPC能帮你解决什么问题?
我简单列几个痛点,你看看是不是也遇到过:
- 接口文档不同步——service层改了参数,前端调了半天才发现
- 性能不够——JSON解析占CPU,消息体大导致网络带宽吃紧
- 多语言支持难——Java服务、Python服务、Go服务,每个都得重新实现一遍通信逻辑
- 缺乏流式支持——想做个实时推送,得自己搞WebSocket或者轮询
gRPC能一次性把这些坑填平。我个人习惯,只要涉及微服务间的内部通信,优先考虑gRPC。对外部接口,还是用REST更合适——毕竟不是所有客户端都装了protobuf解码器嘛。
1.3 gRPC的四大核心特性
| 特性 | 说明 | 我的一点体会 |
|---|---|---|
| 基于HTTP/2 | 复用连接、头部压缩、支持服务器主动推送 | 压测时能看到连接数比REST少一个数量级 |
| 使用Protocol Buffers | 高效的二进制序列化格式,体积小、速度快 | 同样的数据,protobuf比JSON小3~10倍 |
| 支持多种调用模式 | Unary、服务端流、客户端流、双向流 | 做实时推送场景时,双向流简直救了我 |
| 跨语言、跨平台 | 官方支持C++、Java、Go、Python、Ruby等十多种语言 | 我们Java后端和Python算法组,用同一个proto文件,谁都不用迁就谁 |
1.4 那HTTP/2到底好在哪里?
你会问,REST也能用HTTP/2啊,凭啥gRPC就特别快?
嗯,关键在于gRPC强制使用HTTP/2,并且充分利用了它的特性。我来拆解一下:
- 二进制分帧层——HTTP/1.x是文本协议,HTTP/2是二进制协议,解析效率更高
- 多路复用——一个TCP连接可以并发处理多个请求,不会出现HTTP/1.x的队头阻塞
- 头部压缩——使用HPACK算法压缩请求头,减少冗余数据
- 服务器推送——服务端可以主动向客户端推送内容,减少请求次数
我记得第一次压测gRPC接口时,看到CPU占用率比REST接口低了快40%,带宽也省了一半。那一刻我真的信了——技术选型对了,运维成本能省一大截。
小提示:gRPC虽然底层用HTTP/2,但你不必直接操作HTTP/2的API。框架已经帮你封装好了。你只需要关心proto文件怎么写,业务逻辑怎么实现。
1.5 再聊聊Protocol Buffers
Protocol Buffers,简称protobuf。它是一种与语言无关、平台无关的序列化格式。你用.proto文件定义数据结构,然后用protoc编译器生成各语言的代码。
一个典型的proto文件长这样:
syntax = "proto3";
package user;
service UserService {
rpc GetUser(GetUserRequest) returns (GetUserResponse);
}
message GetUserRequest {
int32 user_id = 1;
}
message GetUserResponse {
string name = 1;
int32 age = 2;
string email = 3;
}
你看,定义清晰,自动生成代码,不用再手写JSON序列化和反序列化。而且proto文件本身就是接口文档,文档即代码,代码即文档。
我曾经遇到过一个坑:团队里有人把protobuf和JSON混用,结果序列化格式不一致,导致解析失败。我的建议是——一旦确认用protobuf,就从头到尾统一,别搞两套。
1.6 gRPC vs REST——该选谁?
你可能会纠结:什么时候用gRPC,什么时候用REST?
我直接给你一个判断标准,用表格对比比较清楚:
| 对比维度 | gRPC | REST |
|---|---|---|
| 传输格式 | 二进制(protobuf) | 文本(JSON/XML) |
| 性能 | 高 | 一般 |
| 浏览器支持 | 需要gRPC-Web | 原生支持 |
| 调试友好度 | 需要工具解析 | 直接curl就能看 |
| 流式支持 | 原生支持 | 需额外实现 |
| 适合场景 | 微服务内部、低延迟、高吞吐 | 对外API、浏览器客户端 |
1.7 咱们这门课要干什么?
好了,基础介绍到这里。你已经有概念了:gRPC很强大,性能和安全性都很棒。
但有个问题——gRPC默认没有对通信内容做透明加密。虽然它支持TLS,但那属于传输层加密。如果你想在应用层做更细粒度的加密改造,或者需要兼容已有的加密体系,那就得自己动手。
这门课的目标,就是带你一步步把gRPC接口改造为透明加密。从协议设计、密钥管理、安全认证,到实际代码实现和性能调优。你会学到怎么在不入侵业务逻辑的前提下,给每个RPC调用加上一把锁。
嗯,思路清楚了就往下走吧。先看我画的一张图,把gRPC的体系结构给你理一遍。
从这张图你能看出来,gRPC的核心是HTTP/2 + Protocol Buffers,它们共同支撑起高性能通信。而四种调用模式,则让你能灵活应对不同的业务需求。
特别注意:如果你用的是Java,io.grpc包和protobuf-java的版本一定要匹配。我曾经吃过版本不兼容的亏,编译通过了,运行时一直报Method not found。排查了半天,最后发现是protobuf版本差了0.1。
好了,第一章就到这里。你对gRPC已经有了一个整体认知。下一件事,就是准备好环境,咱们开始实战。但先别急——我会带你把基础概念夯实,再动手写代码。
过程中有任何困惑,记得回到这一章来重新梳理图上这些关系。清楚了体系,后面才能走得稳。