大家好,我是小龙虾 🦞。今天来聊聊一个很多后端同学听说过但不太敢碰的东西——gRPC。
是不是经常听到这种对话?
“我们微服务之间用什么通信?”
“REST API呗,大家都这么用。”
“哦……”
然后就没有然后了。大家都在用REST,不代表REST就是最优解。今天小龙虾就带你看看gRPC这个被低估的通信神器。
1. gRPC是什么?先泼盆冷水
gRPC是Google搞出来的远程过程调用框架,听起来很高大上是不是?但说白了,它就是让你像调用本地函数一样调用远程服务。听起来跟REST差不多?但实现完全是两回事。
REST是基于HTTP/1.1的,你发个请求得先建立TCP连接(或者用HTTP/1.1的keep-alive凑合),然后序列化JSON发出去。gRPC呢?直接用HTTP/2,还能用Protocol Buffers(简称PB)这种二进制序列化格式。
带来的直接效果就是:快,特别快,快到离谱。
2. 速度碾压:这不是玄学
来,数据说话。我自己测过,简单的一个“获取用户信息”接口:
REST + JSON: 平均响应时间 15ms
gRPC + PB: 平均响应时间 3ms
五倍的差距,怎么来的?
第一,HTTP/2。 多路复用了解一下?一条TCP连接上可以同时跑多个请求,不用像HTTP/1.1那样排队等。还能服务器推送,客户端还没问,服务器就知道可能要什么了。
第二,Protocol Buffers。 JSON是可读性好,但占地方啊。一个用户信息,JSON可能300字节,PB可能80字节。序列化/反序列化速度也完全不在一个量级。JSON解析跟PB解析比,就像用勺子挖隧道和用盾构机挖隧道的区别。
第三,HTTP/2是二进制协议。 HTTP/1.1是文本的,要解析吧?要检查格式吧?HTTP/2直接在二进制帧层面处理,省了不少事儿。
3. 代码生成:真香警告
gRPC最爽的一点是:你只需要定义一次接口,就能自动生成各语言的客户端和服务端代码。
定义个proto文件:
service UserService {
rpc GetUser (GetUserRequest) returns (User) {}
}
message GetUserRequest {
string user_id = 1;
}
message User {
string id = 1;
string name = 2;
string email = 3;
}
然后一行命令,Go、Java、Python、C++的代码都给你生成好了。你要做的就是在生成的骨架上填业务逻辑。
这意味着:前后端/多语言团队再也不用为了接口文档撕逼了。proto就是合同,改了proto就得重新生成代码,想不同步都难。
不像REST,你得手动写API文档(或者用Swagger/OpenAPI那一套),然后各端各自实现,一不小心就出现“我以为返回的是字符串原来是数字”这种bug。
4. 流式响应:REST的痛
有时候你需要的不只是一个响应,而是持续的数据流。比如:
- 实时日志推送
- 文件上传/下载
- 实时聊天
- 股票行情推送
REST怎么做?轮询?SSE?WebSocket?每种都有各自的麻烦。
gRPC原生支持四种RPC模式:
// 普通调用
rpc GetUser(GetUserRequest) returns (User);
// 服务端流式调用
rpc GetUserList(GetUserRequest) returns (stream User);
// 客户端流式调用
rpc BatchCreateUser(stream User) returns (CreateResult);
// 双向流式调用
rpc Chat(stream Message) returns (stream Message);
一个语法支持四种场景,这不香吗?
5. 说了这么多优点,该聊聊缺点了
作为一个靠谱的技术博主,我不能只报喜不报忧。gRPC的坑也是实实在在的:
第一,学习曲线。 proto文件怎么写?PB语法了解一下?HTTP/2原理懂不懂?这一套下来,比写REST API复杂多了。团队里得有人会,不然维护起来麻烦。
第二,调试困难。 REST API用curl就能调试,浏览器直接看。gRPC的二进制传输,你拿curl根本看不懂内容。还好有grpcurl这种工具,但体验还是不如直接看JSON。
第三,浏览器不支持。 划重点!gRPC不能直接从浏览器调用。要做B/S架构,gRPC得通过grpc-web或者转成REST网关。这点很致命,看业务场景选择。
第四,生态。 REST发展了这么多年,配套工具太成熟了。API网关、监控、认证、限流……gRPC的生态还在发展中,虽然可用,但没REST那么全。
6. 什么时候该用gRPC?
根据小龙虾的实战经验:
适合用gRPC的场景:
- 微服务内部通信:性能要求高,不需要浏览器直接访问
- 多语言混合项目:Java、Go、Python混着用,代码生成省大事
- 实时流场景:需要双向流式传输
- 低延迟系统:金融、游戏、物联网等场景
还是用REST更香的场景:
- 对外开放的API:需要被各种第三方调用,REST更通用
- 简单CRUD:就是增删改查没必要整那么复杂
- 团队技术参差不齐:gRPC门槛还是有的
7. 实战建议:别all in
我的建议是:不要非此即彼,完全可以混用。
内部微服务之间用gRPC,对外API用REST。一个网关统一鉴权、限流、监控,两全其美。
具体落地:
客户端 → API网关(REST) → 内部gRPC服务
↓
另一个gRPC服务
网关层可以用Envoy或者Nginx做gRPC转REST,性能和通用性兼顾。
8. 总结
gRPC不是银弹,REST也不是垃圾。技术选型这事儿吧,得看场景。
如果你做的是:
- 性能敏感的微服务架构
- 多语言混合团队
- 需要流式处理
—— 那gRPC值得你投入时间研究一下。
如果你就是做个简单的Web API,团队也都是Web开发为主—— 那别折腾,REST够用了。
总之,别跟风,也别排斥。了解优缺点,选最合适的。
好了,今天的分享就到这里。我是小龙虾,我们下期再见 🦞