为什么 RPC 要比 HTTP 更快?


面试考察点

  1. 协议理解深度:面试官不仅仅是想知道 RPC 比 HTTP 快,更是想知道你是否理解 HTTP/1.1 的协议开销(Header 冗余、文本格式编码),以及 RPC 框架在协议层做了哪些精简。
  2. 序列化机制认知:考察你是否清楚 JSON/XML 这类文本序列化方式与 Protobuf、Hessian 等二进制序列化的性能差距,以及背后的原因。
  3. 连接管理意识:看你是否了解长连接复用、连接池管理对性能的影响,以及 HTTP 短连接模型的固有开销。
  4. 工程辨析能力:一个加分项——能否客观地说出 "RPC 不一定总是比 HTTP 快",比如 HTTP/2 和 gRPC 的出现已经大幅缩小了这个差距。

核心答案

先说结论:RPC 之所以比传统 HTTP(特指 HTTP/1.1 + JSON)更快,核心原因有 4 个——

维度 HTTP/1.1 + JSON RPC(Dubbo/gRPC 等) 性能差距
协议格式 文本协议,Header 臃肿 自定义二进制协议,精简高效 报文体积差距 3~10 倍
序列化方式 JSON(文本) Protobuf/Hessian(二进制) 序列化速度差距 5~20 倍
连接模型 短连接为主 / Keep-Alive 有限复用 长连接 + 连接池 减少 TCP 握手开销
网络模型 BIO/NIO 混用 NIO/Epoll 优化的 Netty 高并发吞吐量差距明显

下面一个个拆开讲。

深度解析

一、协议格式:报文 "臃肿" vs "精瘦"

HTTP/1.1 的报文头是纯文本的,每次请求都要携带一大堆 Header 信息。来看个直观的例子:

上图展示了 HTTP 和 RPC 在报文结构上的核心差异。关键点:

  • HTTP/1.1 的 Header 是文本格式,每次请求都要带上 Content-TypeUser-AgentAccept 等一堆跟业务无关的信息。这些 Header 在内部服务调用中完全多余,但协议规定必须解析。
  • Dubbo 的协议头只有固定的 16 字节(Magic Number + Flag + Status + Request ID + Data Length),极其精简。没有废话,全是干货。
  • 实际场景中,一个简单的 HTTP 接口调用,Header 可能就占了 300~800 字节,而 RPC 协议头只有 16 字节。在高频调用下,这个差距会被无限放大。

二、序列化:文本 vs 二进制

这是性能差距最大的一块。

HTTP 最常用的序列化格式是 JSON,而 RPC 框架通常使用二进制序列化(Protobuf、Hessian、Kryo 等)。两者差距在哪?

上图直观展示了 JSON 和 Protobuf 在序列化后的数据差异。核心原因有三点:

  • 字段名冗余:JSON 每次都要把字段名 "id""name" 完整地传一遍,而 Protobuf 用字段编号(12)代替,接收端通过 .proto 文件反序列化时再映射回字段名。数据量直接砍半。
  • 类型编码低效:JSON 中数字 12345 按 ASCII 字符存储,占 5 字节。Protobuf 用 Varint(变长整数)编码,只占 3 字节。整数越大差距越明显。
  • 格式符号冗余:JSON 的 {}"":, 这些格式符号在二进制协议中全部可以省略,用 Tag-Length-Value(TLV)结构替代。

实际压测数据参考:

序列化方式 序列化耗时 反序列化耗时 数据大小
JSON(Jackson) ~5ms ~8ms 100%
Hessian2 ~3ms ~4ms ~60%
Protobuf ~1ms ~1.5ms ~30%
Kryo ~0.8ms ~1ms ~35%

以上数据为同一条复杂对象 10 万次序列化的参考值,实际数值取决于数据结构和运行环境。

三、连接模型:短连接开销 vs 长连接复用

HTTP/1.1 默认虽然支持 Keep-Alive,但在实际使用中,很多客户端(尤其浏览器)连接复用效率并不高。而 RPC 框架天生就是基于长连接设计的。

上图对比了三种连接模型。重点说说 RPC 的优势:

  • TCP 连接建立开销:一次 TCP 三次握手需要 1.5 个 RTT(Round-Trip Time),如果走 TLS 还要额外 2 个 RTT。在同机房 RTT 约 0.5ms,跨机房可能 5~30ms。高频短连接场景下,这个开销非常可观。
  • RPC 框架直接基于 Netty 做 NIO 多路复用,一个 TCP 连接上可以同时跑多个请求,通过 Request ID 做关联,互不阻塞。
  • Dubbo 还支持连接池多连接,可以根据并发量动态调整。默认情况下,消费者与每个提供者建立单个长连接,对于高并发场景可以配置多个连接。

四、网络模型:BIO vs NIO

这个维度很多人会忽略。

传统的 HTTP 服务(比如早期的 Servlet 容器)多采用 "一请求一线程" 的 BIO 模型,并发量大的时候线程数暴涨,上下文切换开销巨大。

而主流 RPC 框架(Dubbo、gRPC)底层都是基于 Netty 的 NIO 模型:

  • 少量线程(通常等于 CPU 核心数)即可处理大量并发连接
  • 基于 Linux epoll 的 IO 多路复用,单线程可以同时监听数千个连接
  • 避免了线程上下文切换和锁竞争的开销

说白了,网络模型决定了 "天花板" 有多高。协议再精简,如果每个请求都占用一个线程,并发一上去照样扛不住。

五、一个容易被忽略的点——RPC 框架的 "额外优化"

除了上面 4 个核心差异,成熟的 RPC 框架还做了一些 HTTP 原生不提供的优化:

  • 服务发现:RPC 框架内置注册中心(Nacos、ZooKeeper),自动感知服务上下线,HTTP 需要额外引入负载均衡组件
  • 智能路由:基于权重、一致性哈希、同机房优先等策略的流量调度
  • 熔断降级:集成 Sentinel、Hystrix 等组件,快速失败
  • 泛化调用:不需要客户端 SDK,直接传参调接口

这些不算 "速度" 上的优势,但它们让 RPC 在微服务架构中的整体效率远高于裸 HTTP 调用。

常见误区

误区:HTTP 一定比 RPC 慢。

这个说法已经过时了。HTTP/2 引入了二进制分帧、多路复用、Header 压缩(HPACK),性能大幅提升。gRPC 更是直接基于 HTTP/2 + Protobuf,性能已经非常接近传统 RPC 框架。

所以更准确的说法是:RPC(自定义协议)比 HTTP/1.1 + JSON 快,但 HTTP/2 + Protobuf 的性能已经和传统 RPC 不相上下了。

面试高频追问

  1. 追问一:既然 RPC 这么好,为什么还要用 HTTP?

    HTTP 的优势在于 通用性和生态。浏览器原生支持 HTTP,API 网关、CDN、防火墙都围绕 HTTP 协议工作。对外暴露的 API(OpenAPI、移动端接口)几乎都用 HTTP,对内微服务间调用才用 RPC。这也是为什么很多公司采用 "外 HTTP 内 RPC" 的架构。

  2. 追问二:gRPC 算 RPC 还是 HTTP?

    gRPC 是基于 HTTP/2 的 RPC 框架。它用 HTTP/2 做传输层,用 Protobuf 做序列化,兼具了 HTTP 的通用性和 RPC 的高性能。所以说,HTTP 和 RPC 并不是对立的,gRPC 就是两者结合的产物。

  3. 追问三:Dubbo 和 Spring Cloud(OpenFeign)的性能差距大吗?

    Dubbo 使用自定义 TCP 协议 + Hessian2/Protobuf 序列化,OpenFeign 本质是 HTTP + JSON。在同样的硬件条件下,Dubbo 的吞吐量通常是 OpenFeign 的 2~5 倍,延迟也低 30%~50%。不过 Spring Cloud 6 已经开始支持 gRPC,差距在缩小。

常见面试变体

  • 变体一:"HTTP 和 RPC 的本质区别是什么?"
  • 变体二:"为什么微服务内部调用推荐用 RPC 而不是 HTTP?"
  • 变体三:"gRPC 和 Dubbo 性能上有什么差异?"
  • 变体四:"什么场景只能用 HTTP,不能用 RPC?"

记忆口诀

RPC 快的四个字:"精、二、长、N"

  • :协议精简,16 字节头部 vs 几百字节 HTTP Header
  • :二进制序列化,体积小、速度快
  • :长连接复用,省去 TCP 握手开销
  • N:NIO 网络模型,少量线程扛高并发

总结

一句话:RPC 比传统 HTTP/1.1 快,核心在于 协议更精简、序列化更高效、连接复用更好、网络模型更优秀。但别忘了,HTTP/2 + gRPC 已经在缩小这个差距,面试时千万别说 "HTTP 就是比 RPC 慢",要说清是 "HTTP/1.1 + JSON" vs "自定义协议 + 二进制序列化" 的差异,这才是面试官想听的。