1724 字
约 5 分钟
9
S02-B09 · HTTP 与 RPC:为什么 RPC 更快,又为什么仍要 HTTP

适用读者:被问"为什么不用 REST 全替代 RPC"的人;要在 gRPC / HTTP+JSON 之间选型的人。
前置:S02-B06(HTTP 与 HTTPS)、S02-B08(长连接)。
实测环境:Python 3.12 + protobuf 7.36.2(venv);实测日期 2026-11-05。
覆盖旧文:A-913(HTTP 与 RPC 的区别,81 点)、A-1050(为什么 RPC 比 HTTP 快,94 点)、A-1564(Feign 与 HTTP 客户端,56 点,跨 S17)= 231 点。
覆盖扩展:E-S02-017(Protobuf vs JSON)、E-S02-018(HPACK)。
上一篇:S02-B08 · 实时通信的稳定性:断线、重连、心跳与幂等
下一篇:S02-B10 · 从 OpenAPI 到可执行工具。


1. 一句话结论

RPC 与 HTTP 不是同一层的东西。 HTTP 是"传输协议",RPC 是"远程调用的编程模型"——RPC 完全可以跑在 HTTP 之上(gRPC 就是)。

所以"RPC 比 HTTP 快"这句话严格来说不成立,正确的说法是:

"二进制序列化 + 头部压缩 + 长连接复用 + 更少的语义开销" 这四件事加起来,让典型 RPC 调用比典型 REST/JSON 调用更快。


2. 实测:序列化能省多少

同一份业务记录(id、用户名、金额、状态、标签数组):

# 单条
Protobuf = 43 B | JSON(UTF-8) = 106 B | 比例 2.47x
# 1000 条
Protobuf = 43000 B | JSON = 108000 B | 比例 2.51x
# 解析耗时(10000 次)
Protobuf 0.016s | JSON 0.090s
指标 Protobuf JSON 差异
单条体积 43 B 106 B 2.47×
批量体积 43 KB 108 KB 2.51×
解析 1 万次 0.016 s 0.090 s 5.6×

为什么差这么多:

原因 说明
字段名不传输 JSON 每条都带 "user_name":;Protobuf 只传字段号(1、2、3)
变长整数编码 1234567890123 在 JSON 是 13 个字符,Protobuf 用 varint 只需 6 字节
无引号/无逗号/无括号 结构信息在 schema 里,不在报文里
解析是二进制偏移 不需要词法分析,直接按 schema 读

别过度引申:2.5 倍的体积差异在大带宽场景意义有限;真正的收益在"高频小消息 + 移动网络"。


3. 性能差距的四个来源

来源 HTTP/1.1 + JSON RPC(gRPC 为例) 差多少(量级)
① 序列化 文本,体积大、解析慢 二进制,紧凑、解析快 2–5×(本文实测)
② 头部开销 每个请求几百字节文本头 HTTP/2 + HPACK 压缩 高频小请求下显著
③ 连接复用 keep-alive 也可复用 多路复用(一条连接并发多流) 并发高时显著
④ 语义开销 每次要构造/解析 HTTP 语义 直接方法调用 → 编解码 小但存在

3.1 关于 ②:HPACK 到底省了什么(E-S02-018)

HTTP/2 的头部压缩用"静态表 + 动态表":content-type、user-agent 这类重复出现的头部只传一个索引号,不再传字符串。

实测含义:如果每个请求头部 400 字节、body 50 字节,那么 HTTP/1.1 下 89% 的流量是头部;HTTP/2 压缩后可能降到几十字节——这就是"高频小请求"场景下 HTTP/2 的收益来源。


4. 对照表:REST/JSON 与 gRPC

维度 REST + JSON gRPC
契约 OpenAPI(可选) .proto 强制
序列化 JSON Protobuf
传输 HTTP/1.1 或 2 必须 HTTP/2
浏览器直连 ✅ 原生 ❌ 需要 grpc-web + 代理
流式 SSE/WebSocket 另配 内建四种流(单向/服务端/客户端/双向)
可调试性 ✅(curl 直接看) ⚠️ 需 grpcurl 与 proto
版本兼容 靠约定 字段号 + reserved(更严格)
生态 全语言、全工具 主流语言,工具链较重

5. 选型判据(三问)

谁在调用?
├── 浏览器 / 第三方 / 公开 API  → HTTP + JSON(REST)
└── 内部服务之间
        ├── 高频、低延迟、强契约 → gRPC
        └── 低频、调试优先       → HTTP + JSON 也行
判据 选 HTTP/JSON 选 gRPC/RPC
调用方是浏览器 ✅ ❌
需要人工调试/抓包看内容 ✅ ⚠️
内部服务、QPS 高、消息小 ⚠️ ✅
需要双向流(实时同步) ❌ ✅
跨语言、多团队 ⚠️ ✅(proto 是契约)

一句总结:对外用 HTTP,对内视规模用 RPC,两者可以共存(网关做转换)。


6. 关于 Feign 与 HTTP 客户端(A-1564,跨 S17)

旧文 A-1564 是"Feign 与 HTTP 客户端"的面试口径。这里只给结论,细节归 S17:

客户端 特点 适用
RestTemplate 同步阻塞、简单 传统 Spring 项目
WebClient 响应式、非阻塞 高并发、Spring WebFlux
OpenFeign 声明式接口,集成服务发现与负载均衡 Spring Cloud 微服务
HttpClient(JDK 11+) 支持 HTTP/2、异步 轻量场景

判据:已经在 Spring Cloud 体系内 → Feign;否则不要为了"声明式"引入整套 Cloud 依赖。


7. 五个误区

误区 真相
"RPC 比 HTTP 快,所以都该用 RPC" RPC 常跑在 HTTP/2 上;差距主要来自序列化与头部
"JSON 慢到不能用" 差异 2–5 倍,但网络 RTT 往往是主要成本
"gRPC 一定省带宽" 小消息省;大二进制(图片/文件)两者都不该走 RPC
"HTTP/2 开了就快" 高频小请求才明显;大文件传输提升有限
"Feign 就是 HTTP 客户端" 它是"声明式 + 服务发现 + 负载均衡"的组合,重的是生态

8. 自测

  1. 为什么说"RPC 比 HTTP 快"这句话不严谨?
  2. 序列化差异的四个具体来源是什么?
  3. HPACK 在什么场景下收益最大?
  4. 浏览器直连的 REST 与 gRPC,本质限制在哪?
  5. 内部服务 QPS 很高但消息很大(几十 KB),你会怎么选?

9. 下一篇

S02-B10 · 从 OpenAPI 到可执行工具:API 描述如何变成插件

接口协议选完,下一个问题是"怎么让机器理解一个 API"。下一篇把旧文 A-647/A-649 的内容重组成:OpenAPI 描述 → 工具 schema → 真实 HTTP 调用 的完整链路,并指出"缺哪几项就无法安全调用"。


本篇属于系列《S02 · 计算机与网络基础》。旧文来源:A-913、A-1050、A-1564(跨 S17);扩展点 E-S02-017/018。Protobuf/JSON 对比为 2026-11-05 实测(protobuf 7.36.2)。

S02-B09 · HTTP 与 RPC:为什么 RPC 更快,又为什么仍要 HTTP
https://www.clxhxhhr.top/posts/5190/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。