目录

既然有了 HTTP,为什么还要用 gRPC?

很多人第一次接触微服务会卡在一个问题上:HTTP 都能传数据了,为什么团队里还要再上一套 gRPC?

我自己一开始也觉得这是重复造轮子,后来真正去抠两者的底层才发现,它们解决的根本不是同一层的事。

下面从最底下的 TCP 一路往上讲清楚。

裸 TCP 为什么不够用?

TCP 能收发数据,但它给你的是一段没有边界的字节流

你往里写了两次数据,对端读出来可能黏成一坨,也可能被拆成三段。

TCP 只保证字节按顺序到达,从不告诉你"这一条消息到哪儿结束"。

所以上层必须自己定一套规矩,约定消息怎么分割、怎么解析。

这套规矩就是应用层协议。

HTTP 是这么干的,各类 RPC 协议也是这么干的。

它们都站在 TCP 肩膀上,只是定义边界和格式的方式不一样。

说白了,协议这东西的第一份工作,就是给字节流划线。

RPC 到底是什么?

先纠正一个常见误解:RPC 本身不是某个具体协议,而是一种调用思路

RPC 全称 Remote Procedure Call,远程过程调用。

它的目标很朴素:让你调用远端服务,写起来跟调用本地函数一模一样。

// 看起来就是普通函数调用
user, err := userClient.GetUser(ctx, &pb.GetUserReq{Id: 1001})

底层其实经历了参数序列化、网络传输、远端反序列化、执行、结果回传一整套流程,但这些都被框架藏起来了。

gRPC、Thrift、Dubbo 这些才是 RPC 思想的具体实现,它们各自定义了自己的协议。

还有个容易忽略的点:RPC 不一定非要跑在 TCP 上。

它只关心"远程调用"这件事,传输层用什么并不强制。

既然 HTTP 能用,为啥还要 RPC?

这才是核心问题。我把原因拆成三块。

一是历史顺序。

RPC 的概念在上世纪八十年代就有了,比 1991 年诞生的 HTTP 还早。

很多公司内部的服务通信,早在 HTTP 流行前就用上了 RPC,这套基础设施一直沿用至今,没必要硬改。

二是性能。

传统的 HTTP/1.1 是纯文本协议,头部冗长、还有队头阻塞的毛病。

RPC 框架普遍用二进制编码,数据更紧凑,解析更快。

在机房内部成千上万次的服务调用里,这点差距会被放得很大。

三是使用场景的分工。

有个流传很广的说法:HTTP 偏向 B/S 架构(浏览器和服务器),RPC 偏向 C/S 架构(客户端和服务器)。

现在这条界线已经很模糊了,但实践中仍有个默契——对外暴露的接口走 HTTP,方便各种客户端和浏览器对接;集群内部微服务互相调用走 RPC,图的就是快和省。

gRPC 凭什么跑得快?

gRPC 是 Google 开源的 RPC 框架,它把性能优势主要押在两件事上。

底层用 HTTP/2。

别被名字骗了,gRPC 虽然带个 RPC,但它是架在 HTTP/2 之上的。

HTTP/2 带来了多路复用(一条连接跑多个请求、互不阻塞)、头部压缩、二进制分帧这些能力,比 HTTP/1.1 强一大截。

默认用 Protobuf 序列化。

Protocol Buffers 是二进制格式,相比 JSON 这种文本格式,体积通常能小好几倍,编解码也快。

你先写一份 .proto 接口定义文件,工具就能自动生成各种语言的客户端和服务端代码,强类型、跨语言,省去手写一堆样板。

gRPC 还原生支持四种调用方式:

  • 一元调用(普通的一问一答)
  • 服务端流式(客户端发一次,服务端持续推)
  • 客户端流式(客户端持续发,服务端最后回)
  • 双向流式(两边同时持续收发)

流式这块是 HTTP/1.1 时代很难优雅做到的,对实时推送、大文件传输这类场景特别合适。

一张表看清区别

维度 HTTP/1.1 gRPC
传输底层 TCP HTTP/2 over TCP
数据格式 文本(常配 JSON) 二进制(Protobuf)
接口定义 无强制,靠文档约定 .proto 文件,强类型
多语言 各写各的 自动生成多语言代码
流式支持 四种流模式原生支持
可读性 高,肉眼可读 低,需要工具解析

HTTP/2 出来了,会取代 RPC 吗?

短期内不会。

HTTP/2 在 HTTP/1.1 基础上补了多路复用、头部压缩等优化,性能确实逼近甚至追平了不少 RPC 协议。

但它普及得相对晚,而企业内部那套 RPC 体系已经盘根错节地跑了很多年,迁移成本和稳定性风险摆在那儿,没人会为了一点性能去动核心链路。

而且 RPC 给的不只是性能,还有完整的服务治理生态——服务发现、负载均衡、熔断限流、链路追踪,这些才是大厂离不开它的真正原因。

换句话说,gRPC 和 HTTP 不是你死我活,更多是各管一段。

常见问题

gRPC 和 HTTP 是同一个层级的东西吗?

不完全是。

HTTP 是应用层协议,gRPC 是一套 RPC 框架,它本身就跑在 HTTP/2 这个协议之上

所以严格说,gRPC 和 HTTP/1.1 比较才对等,而它和 HTTP/2 是"使用"关系,不是竞争关系。

gRPC 一定比 HTTP 快吗?

大多数内部高并发场景下是的,靠的是 HTTP/2 多路复用加 Protobuf 二进制编码。

但如果是对外的简单接口、调用频率不高,HTTP + JSON 的可读性和调试便利性反而更划算,没必要为了快硬上 gRPC。

浏览器能直接调用 gRPC 吗?

不能直接调用。

浏览器对 HTTP/2 的底层帧控制有限,调原生 gRPC 会受限,通常得通过 gRPC-Web 加一层代理转换。

这也是为什么对外接口大多还是用普通 HTTP。

Protobuf 比 JSON 好在哪?

主要是体积小、编解码快、带强类型约束。

代价是不可读、改字段要重新生成代码。

内部服务通信适合 Protobuf,对外开放接口 JSON 仍是主流。

写在最后

绕了一圈你会发现,“有了 HTTP 为什么还要 gRPC"这个问题,本质上是把两个不同层面的东西放一起比了。

HTTP 解决的是通用、跨端、可读的通信;

gRPC 解决的是内部高频、高性能、强类型的服务调用。

我自己的经验是:对外网关用 HTTP,内部微服务用 gRPC,基本不会错。

真到了要选型那一步,看的是场景,不是谁更"先进”。

如果你在选型或者接 gRPC 时踩过别的坑,欢迎在评论区聊聊,我也想知道还有哪些我没碰到的情况~~~

版权声明

未经授权,禁止转载本文章。
如需转载请保留原文链接并注明出处。即视为默认获得授权。
未保留原文链接未注明出处或删除链接将视为侵权,必追究法律责任!

本文原文链接: https://fiveyoboy.com/articles/why-grpc-when-we-have-http/

备用原文链接: https://blog.fiveyoboy.com/articles/why-grpc-when-we-have-http/