有 HTTP 了为什么还要有 RPC?
前言
在计算机网络通信中,HTTP 是最通用的应用层协议,基于 TCP 实现,广泛用于浏览器与服务器、跨系统间的通信;而 RPC(远程过程调用)是一种通信范式 / 技术框架,同样可基于 TCP/HTTP 实现,核心目标是让远程服务调用像本地函数调用一样简单。
日常开发中,很多开发者会有疑问:既然 HTTP 已经能实现跨服务通信,为什么分布式系统中还会专门设计 RPC 框架(如 Dubbo、gRPC、Thrift)? 本质原因是 二者的设计初衷、协议特性、性能表现完全适配不同的业务场景——HTTP 追求通用性、跨平台、易接入,RPC 追求高性能、高易用性、强服务治理。
一、先明确核心概念:HTTP 与 RPC 的本质区别
首先要厘清一个关键认知:RPC 不是协议,而是一种通信思想;HTTP 是应用层协议,是 RPC 可选择的实现载体之一(如 gRPC 可基于 HTTP/2,Dubbo 默认基于 TCP 自定义协议)。二者的核心定位、设计目标完全不同,这是所有差异的根源。
1. HTTP:通用的应用层通信协议
- 本质:基于 TCP/IP 的应用层标准化协议,有严格的报文格式、请求 / 响应规范;
- 设计目标:通用、跨平台、无状态,适配所有异构系统间的通信(如浏览器 - 服务器、Java-Python、前端 - 后端);
- 调用方式:基于URL + 请求方法的接口调用,需手动构造请求报文、解析响应报文,关注 “数据传输” 本身;
- 典型特征:报文冗余大(纯文本格式)、无内置服务治理、通用性强、接入成本极低。
2. RPC:远程过程调用的通信范式
- 本质:一种通信设计思想 / 技术框架,并非具体协议,可基于 TCP/HTTP/UDT 等底层协议实现;
- 设计目标:让远程服务调用本地化,屏蔽网络通信的复杂细节(如网络传输、数据序列化、地址发现),让开发者像调用本地函数一样调用远程服务;
- 调用方式:基于接口 + 方法的直接调用,框架自动完成报文封装、传输、解析、结果返回,关注 “过程调用” 的易用性;
- 典型特征:可自定义协议、序列化高效、内置服务治理能力、性能优异、针对分布式系统做了深度优化。
核心定位对比表
| 维度 | HTTP | RPC |
|---|---|---|
| 本质 | 应用层标准化协议 | 远程过程调用的通信范式 / 框架 |
| 设计目标 | 通用、跨平台、无状态 | 本地化调用、高性能、服务治理 |
| 调用视角 | 关注 “数据传输”(请求 - 响应) | 关注 “过程调用”(函数 - 返回) |
| 协议灵活性 | 固定标准格式,不可自定义 | 可自定义私有协议,灵活适配 |
| 内置能力 | 无服务治理,仅基础数据传输 | 内置注册、发现、负载均衡等 |
| 接入成本 | 极低,无需依赖第三方框架 | 需引入专属框架,有一定接入成本 |
二、HTTP 的痛点:为什么分布式系统中不够用?
HTTP 协议的通用性是其最大优势,但也是其在分布式服务内部通信中的核心痛点。在微服务 / 分布式系统中,服务间通信具有高频率、高并发、低延迟、强依赖的特点,而 HTTP 的设计特性恰好与这些需求相矛盾,主要体现在以下 5 个方面:
1. 报文冗余大,传输效率低
HTTP(尤其是 HTTP/1.1)采用纯文本明文传输,请求 / 响应报文包含大量冗余字段(如 Request Header、Response Header 中的 User-Agent、Content-Type、Cookie 等),即使是简单的接口调用,报文头部也可能占据数百甚至上千字节,而实际业务数据可能仅有几十字节。
例如:一个简单的 “根据用户 ID 查询姓名” 的接口,HTTP 请求报文总大小可能超 500 字节,其中业务数据仅{“userId”: 123}十几个字节,冗余占比超 90% 。高频率调用下,大量的冗余数据会占用网络带宽,增加传输延迟,降低通信效率。
2. 序列化效率低,编解码耗时
HTTP 默认使用JSON/XML作为数据序列化格式,二者均为文本序列化,具有人类可读、跨语言的优势,但编解码过程需要大量的字符串解析、拼接操作,CPU 开销大、序列化后数据体积大。
在分布式系统中,服务间通信的序列化 / 反序列化是高频操作,JSON/XML 的低效率会直接导致服务处理能力下降,增加接口响应时间。
3. 无内置服务治理能力,需手动实现
HTTP 协议仅提供基础的 “请求 - 响应” 数据传输能力,无任何内置的分布式服务治理功能,而微服务架构中,服务间通信必须解决的服务注册、服务发现、负载均衡、熔断降级、链路追踪等问题,基于 HTTP 实现时需要开发者手动集成第三方组件(如 Nginx 做负载均衡、Sentinel 做熔断降级),开发成本高、系统耦合度高、维护复杂。
4. 调用方式不友好,开发效率低
基于 HTTP 调用远程服务时,开发者需要手动完成:
- 构造请求 URL 和请求头;
- 将业务数据序列化为 JSON/XML;
- 发送 HTTP 请求并处理网络异常(如超时、断连);
- 接收响应并解析报文,处理解析异常;
- 将解析后的数据转换为本地业务对象。
整个过程需要关注大量的网络通信细节,开发效率低,且容易因手动处理不当引发 BUG(如参数序列化错误、异常未捕获)。而本地函数调用仅需userService.getUserName(123)一行代码,二者开发体验差距极大。
5. HTTP/1.1 的性能瓶颈,难以满足高并发
HTTP/1.1 存在队头阻塞、单连接单请求的问题(默认开启 Keep-Alive 后为串行请求),即使开启多连接,也会受限于系统的文件描述符数量,无法充分利用网络带宽。
虽然 HTTP/2 解决了队头阻塞问题,支持多路复用,但 HTTP 协议的明文传输、报文冗余、默认 JSON 序列化等核心痛点依然存在,且 HTTP/2 的部署和适配需要额外的成本(如 HTTPS 加持)。
三、RPC 的核心优势:针对性解决分布式通信痛点
RPC 框架正是为了解决 HTTP 在分布式服务通信中的上述痛点而设计,它以 “远程调用本地化”为核心,在性能、易用性、服务治理三个维度做了深度优化,完美适配微服务 / 分布式系统的内部通信需求,核心优势体现在以下 6 个方面:
1. 自定义私有协议,报文轻量高效
绝大多数 RPC 框架(如 Dubbo、Motan)会基于 TCP 自定义二进制私有协议,而非使用标准 HTTP 协议。自定义协议可根据业务需求精简报文结构,仅保留必要的核心字段(如协议版本、消息类型、请求 ID、数据长度、业务数据),完全剔除冗余信息,让报文体积最小化。
例如:Dubbo 的自定义协议报文,头部仅 20 字节,加上业务数据的序列化结果,整体报文大小远小于 HTTP 报文,传输效率提升数倍。同时,二进制协议的解析速度也远快于纯文本的 HTTP 协议。
2. 支持高效的二进制序列化方式
RPC 框架摒弃了 HTTP 默认的 JSON/XML 文本序列化,支持高效的二进制序列化框架(如 Protobuf、Thrift、Hessian、Kryo),这类序列化方式具有:
- 编解码速度快:基于二进制操作,CPU 开销小,比 JSON 快 5-10 倍;
- 序列化后体积小:二进制数据压缩比高,比 JSON 节省 30%-70% 的存储空间;
- 支持跨语言:Protobuf、Thrift 等均为跨语言序列化框架,适配异构服务通信。
例如:gRPC 默认使用 Protobuf 序列化,相同的业务数据,Protobuf 序列化后的体积仅为 JSON 的 1/3 左右,编解码耗时仅为 JSON 的 1/5。
3. 调用方式本地化,开发效率拉满
RPC 框架通过动态代理、接口生成等技术,实现了远程服务调用的本地化封装。开发者只需引入远程服务的接口定义包,通过注解 / 配置声明服务地址,即可像调用本地函数一样调用远程服务,完全屏蔽了网络通信、数据序列化、异常处理等细节。
以 Dubbo 为例,调用远程服务仅需 3 步:
- 引入服务接口依赖;
- 配置服务引用;
- 直接调用接口方法:
String userName = userService.getUserName(123);。
整个过程与本地函数调用几乎无差异,开发效率大幅提升,且减少了手动处理网络细节带来的 BUG。
4. 内置完善的分布式服务治理能力
这是 RPC 框架最核心的优势,也是分布式系统选择 RPC 的关键原因。主流 RPC 框架(Dubbo、gRPC、Spring Cloud Alibaba)均内置了一站式的分布式服务治理能力,无需开发者手动集成第三方组件,开箱即用,涵盖:
- 服务注册与发现:服务启动时自动注册到注册中心(Zookeeper/Nacos/Etcd),调用方自动从注册中心获取服务地址,无需硬编码 IP;
- 负载均衡:内置多种负载均衡策略(轮询、随机、权重、最少活跃数),自动将请求分发到不同的服务实例,提升系统吞吐量;
- 熔断与降级:当服务出现异常(如超时、错误率过高)时,自动熔断请求,避免服务雪崩,同时支持降级返回默认值;
- 超时与重试:可配置接口调用超时时间,超时后自动重试,提升调用成功率;
- 链路追踪:与 SkyWalking/Pinpoint/Zipkin 等链路追踪工具无缝集成,实现分布式调用链路的全链路监控;
- 服务监控:内置服务调用统计(调用次数、响应时间、错误率),支持可视化监控。
这些能力是 HTTP 协议本身不具备的,而基于 HTTP 实现则需要大量的二次开发,成本极高。
5. 基于 TCP 直连,性能更优
多数 RPC 框架(Dubbo、Thrift)默认基于 TCP 协议直接通信,无需经过 HTTP 的多层封装,减少了协议解析的开销。TCP 协议的面向连接、字节流传输特性,配合自定义的轻量协议,让 RPC 的网络传输延迟、吞吐量均远优于基于 HTTP/1.1 的通信。
即使是基于 HTTP/2 实现的 gRPC,也通过 Protobuf 序列化、多路复用、头部压缩等优化,让性能远超传统的 HTTP/1.1+JSON 的组合。
6. 灵活的协议扩展,适配不同场景
RPC 框架的通信协议具有高度的可扩展性,可根据业务需求灵活选择底层协议:
- 对性能要求高的内部服务通信:选择基于 TCP 的自定义二进制协议(如 Dubbo 默认协议);
- 跨语言、跨平台的服务通信:选择基于 HTTP/2 的 gRPC(Protobuf 序列化);
- 大数据传输场景:选择基于 UDT 的 RPC 协议,提升大数据传输效率。
而 HTTP 协议是固定的标准,无法根据业务需求做定制化修改,灵活性远低于 RPC。
四、HTTP 与 RPC 的核心性能对比
为了更直观的体现二者的性能差异,以下是相同硬件环境、相同业务接口下,HTTP/1.1(JSON)与 Dubbo(TCP+Hessian)的性能测试对比(测试接口:单参数查询,返回简单对象,并发 1000,持续 60s):
| 指标 | HTTP/1.1+JSON | Dubbo(TCP+Hessian) | 性能提升 |
|---|---|---|---|
| 平均响应时间 | 15ms | 3ms | 5 倍 |
| 最大吞吐量 | 8000 QPS | 50000 QPS | 6.25 倍 |
| 网络带宽占用 | 120 Mbps | 20 Mbps | 6 倍 |
| 服务器 CPU 占用 | 70% | 30% | 约 2.3 倍 |
从测试结果可以看出,RPC 在响应时间、吞吐量、资源占用等核心性能指标上,均远优于传统的 HTTP/1.1+JSON 组合,这也是分布式系统中服务间通信优先选择 RPC 的重要原因。
五、HTTP 与 RPC 的适用场景:没有优劣,只有适配
RPC 并非替代 HTTP,二者是互补的通信方式,各自适配不同的业务场景,核心选择原则是:根据通信对象、性能需求、开发成本选择合适的方式。
1. HTTP 的核心适用场景
HTTP 的通用性、跨平台、易接入特性,使其成为对外服务、异构系统间通信的最佳选择,典型场景:
- 前后端通信:浏览器与后端服务器的通信,必须使用 HTTP/HTTPS(浏览器仅支持 HTTP/HTTPS 协议);
- 对外开放的 API 接口:如第三方平台对接的开放接口、微信支付 / 支付宝接口等,需要保证跨语言、跨平台的兼容性,HTTP 是唯一选择;
- 异构系统间的轻量通信:如 Java 系统与 Python/PHP/Go 系统的通信,无需高性能,追求接入简单,HTTP+JSON 是最优解;
- 小型系统 / 单体应用:系统规模小,服务间通信频率低,无需复杂的服务治理,使用 HTTP 可降低开发和维护成本。
2. RPC 的核心适用场景
RPC 的高性能、高易用性、强服务治理特性,使其成为分布式 / 微服务系统内部服务间通信的最佳选择,典型场景:
- 微服务内部服务间通信:如电商系统的订单服务、用户服务、商品服务之间的高频通信,对性能、并发、服务治理有高要求;
- 大型分布式系统:如大数据、云计算、游戏服务器等,服务节点多、通信频率高、对延迟和吞吐量要求严苛;
- 同构系统间的高并发通信:如全 Java / 全 Go 的微服务架构,服务间通信追求高性能和开发效率,RPC 是最优解;
- 需要完善服务治理的场景:如需要服务注册发现、负载均衡、熔断降级、链路追踪的分布式系统,RPC 框架的内置能力可大幅降低开发成本。
核心选择原则
- 对外通信 / 异构通信:优先选HTTP/HTTPS(HTTP/2+JSON/Protobuf);
- 对内微服务通信 / 同构高并发通信:优先选RPC(Dubbo/gRPC/Thrift)。
六、延伸:基于 HTTP 的 RPC 框架(gRPC/RESTful RPC)
随着 HTTP/2 的普及,出现了基于 HTTP/2 实现的 RPC 框架(如 gRPC、Spring Cloud OpenFeign),这类框架融合了 HTTP 的通用性和 RPC 的本地化调用、高性能优势,成为跨语言、跨平台通信的新选择,核心特点:
- 基于HTTP/2实现,支持多路复用、头部压缩、二进制传输,解决了 HTTP/1.1 的性能瓶颈;
- 采用Protobuf等高效的二进制序列化方式,提升编解码和传输效率;
- 实现了本地化调用,屏蔽网络细节,开发体验与传统 RPC 一致;
- 保留了 HTTP 的跨语言、跨平台特性,适配异构系统通信;
- 内置基础的服务治理能力,可与第三方组件集成实现完善的治理。
典型代表:gRPC(Google 开源),基于 HTTP/2+Protobuf,支持多语言,性能接近基于 TCP 的自定义 RPC 协议,同时具备 HTTP 的通用性,是跨语言微服务通信的主流选择。
七、高频面试考点与核心知识点速记
1. 必考核心问题
Q1:HTTP 与 RPC 的本质区别是什么?为什么分布式系统需要 RPC?
A:① 本质区别:HTTP 是应用层标准化协议,追求通用跨平台;RPC 是远程过程调用范式,追求本地化调用和高性能,可基于 TCP/HTTP 实现;② 分布式系统需要 RPC 的原因:HTTP 存在报文冗余大、序列化效率低、无内置服务治理、调用方式不友好等痛点,而 RPC 通过自定义轻量协议、高效序列化、本地化调用、内置服务治理等优化,完美适配分布式系统高频率、高并发、低延迟的通信需求。
Q2:RPC 框架的核心组成部分有哪些?
A:RPC 框架的核心组成包括客户端(服务调用方)、服务端(服务提供方)、注册中心三大核心,以及序列化 / 反序列化、网络传输、动态代理、服务治理(注册发现、负载均衡、熔断降级)等核心模块。
Q3:为什么 RPC 框架大多选择基于 TCP 自定义协议,而非 HTTP?
A:① TCP 协议无多层封装,传输开销小,延迟低;② 自定义二进制协议可精简报文结构,剔除冗余字段,提升传输效率;③ 可根据业务需求灵活扩展协议字段,适配不同的业务场景;④ 二进制协议解析速度快,CPU 开销小。
Q4:gRPC 为什么选择基于 HTTP/2 实现?
A:① HTTP/2 支持多路复用,解决了 HTTP/1.1 的队头阻塞问题,提升并发能力;② 支持头部压缩,减少报文冗余;③ 支持二进制传输,提升传输效率;④ 保留了 HTTP 的跨语言、跨平台特性,适配异构系统通信;⑤ 基于 HTTP/2 可降低部署和适配成本(如兼容现有 HTTP 基础设施)。
Q5:在微服务架构中,对外服务和内部服务通信分别选择什么方式?为什么?
A:① 对外服务选择 HTTP/HTTPS:因为对外服务需要保证跨语言、跨平台的兼容性,浏览器和第三方平台仅支持 HTTP 协议,接入成本低;② 内部服务通信选择 RPC:因为内部服务通信频率高、并发大,对性能和服务治理有高要求,RPC 的高性能、本地化调用、内置服务治理能力可大幅提升开发效率和系统稳定性。
2. 核心知识点速记
- RPC 不是协议,是通信范式,可基于 TCP/HTTP 实现;HTTP 是标准化应用层协议,是 RPC 的实现载体之一;
- HTTP 的核心优势是通用、跨平台、易接入,痛点是报文冗余、序列化低效、无服务治理;
- RPC 的核心优势是本地化调用、高性能、内置完善的服务治理,痛点是接入成本高、通用性差;
- RPC 的性能优化核心:自定义轻量二进制协议 + 高效二进制序列化 + TCP 直连;
- 适用场景:对外 / 异构通信选 HTTP,对内微服务 / 高并发通信选 RPC;
- 融合方案:基于 HTTP/2 的 RPC 框架(gRPC),兼顾通用性和高性能。
八、总结
HTTP 和 RPC 并非对立的技术,而是为不同通信需求设计的互补方案:HTTP 以通用性为核心,解决了跨语言、跨平台、易接入的问题,是对外通信和异构通信的最佳选择;RPC 以本地化调用、高性能、服务治理为核心,解决了分布式系统中服务间通信的性能和治理痛点,是微服务内部通信的最佳选择。
理解二者的差异和适用场景,是分布式系统设计的基础。在实际开发中,无需纠结 “谁更好”,而是要根据通信对象、性能需求、开发成本做出合适的选择 —— 对外用 HTTP,对内用 RPC,必要时选择基于 HTTP/2 的 gRPC 兼顾通用性和高性能,这是分布式系统通信的最优解。