RPC 和 HTTP 有什么区别?为什么有了 HTTP 还要用 RPC?
简化版
这俩不是一个层面的东西,不该直接对立。HTTP 是一个应用层协议(规定报文格式);RPC 是一种「调用远程方法」的思想/风格,它需要一个具体协议来传输——底层可以基于 HTTP,也可以基于自定义 TCP 协议。面试问的其实是「RPC 框架(如 Dubbo、gRPC)和 基于 HTTP 的 REST」有什么区别。核心差异:RPC 框架追求「像调本地方法一样调远程服务」,往往用二进制序列化 + 自定义/HTTP2 协议,性能高、内部服务专用;REST/HTTP 通用、跨语言跨平台、浏览器友好、可读易调试。所以:对内微服务高频调用用 RPC(快),对外开放 API 用 HTTP/REST(通用)。
详细版
先厘清概念层次(关键):
- HTTP:具体的应用层协议,规定了请求/响应的报文格式。
- RPC(Remote Procedure Call):一种编程模型/思想——「调用远程方法像调用本地方法」。它不是某个具体协议,需要落地到传输协议上。
- RPC 框架(Dubbo、gRPC、Thrift、brpc):RPC 思想的具体实现,包含序列化 + 传输协议 + 服务发现 + 负载均衡等一整套。
所以「RPC vs HTTP」严格说是范畴错位——RPC 框架也可以用 HTTP 来传(如 gRPC 用 HTTP/2)。面试真正想比的是「典型 RPC 框架 vs 基于 HTTP 的 REST」。
典型 RPC 框架 vs REST/HTTP:
| 维度 | RPC 框架(Dubbo/gRPC…) | REST / HTTP |
|---|---|---|
| 定位 | 内部服务间高性能调用 | 通用、对外开放 |
| 传输协议 | 自定义 TCP 协议 / HTTP2 | 通常 HTTP/1.1 |
| 序列化 | 二进制(Protobuf/Hessian…) | 文本 JSON |
| 性能 | 高(体积小、编解码快) | 相对低 |
| 跨语言/通用 | 需框架支持 | 极好(人人都能调) |
| 服务治理 | 内置(注册发现、负载均衡、熔断) | 需额外网关/组件 |
| 调用体验 | 像调本地方法(生成 stub) | 手动拼 URL、发请求 |
| 可读/调试 | 差(二进制) | 好(可读、易测) |
| 浏览器 | 一般不能直连 | 天然支持 |
完整版教学
一、别掉进「RPC vs HTTP」的伪命题陷阱
这是面试最容易答砸的地方。很多人张口就「RPC 快、HTTP 慢」,其实这两者根本不在同一维度:
- HTTP 是「协议」——它规定「报文长什么样、怎么请求响应」,是传输层之上的一套具体格式。
- RPC 是「思想 / 调用方式」——它描述的是「我想像调本地函数一样调远程服务」这个目标,本身不规定用什么协议传。
证据很直接:gRPC 是 RPC,但它就是基于 HTTP/2 的。所以「RPC 一定不用 HTTP」是错的。正确的对比对象是:「用自定义 TCP 协议 + 二进制序列化的 RPC 框架(如 Dubbo)」 对比 「基于 HTTP/1.1 + JSON 的 REST 风格」。想在面试里显得清醒,先把这个层次说清楚,再展开对比。
二、RPC 框架到底帮你做了什么
RPC 框架的核心目标是屏蔽网络细节,让远程调用写起来跟本地一样:
// 看起来是本地调用,实际底层发了网络请求
OrderResult result = orderService.createOrder(req);
框架在背后完成一整条链路:
- 代理(Stub/Proxy):给接口生成一个本地代理对象,你调它的方法,它帮你发起远程调用。
- 序列化:把方法参数编码成字节流(二进制,紧凑)。
- 传输:通过网络(自定义 TCP 协议或 HTTP/2)发给服务端。
- 服务端处理:反序列化 → 找到真正的实现类 → 执行 → 结果序列化返回。
- 服务治理:还顺带做注册发现(自动找到服务实例)、负载均衡(挑一个实例)、熔断限流、超时重试。
这一整套「网络 + 编解码 + 治理」都被框架封装了,开发者只管定义接口、调方法。REST 则更「原始」——你得自己拼 URL、设请求头、序列化 JSON、处理响应码,服务发现/负载均衡通常靠外部网关或注册中心额外搭。
三、性能差异从哪来
「RPC 比 HTTP/REST 快」的说法有其道理,快在两点:
① 序列化格式:RPC 框架多用二进制序列化(Protobuf、Hessian、Kryo)。二进制比 JSON 文本体积小、编解码快——JSON 每条数据都要重复带字段名、加引号括号,还要做文本解析。
② 传输协议:很多 RPC 框架用精简的自定义 TCP 协议,头部开销小、长连接复用;或用 HTTP/2(多路复用免队头阻塞)。而传统 REST 常跑在 HTTP/1.1 上,头部是臃肿的文本,还受队头阻塞影响。
但要注意:这个「快」在内部微服务高频调用时才明显。对外的、调用频率没那么高的接口,HTTP/JSON 那点开销通常不是瓶颈,通用性和可维护性反而更重要。
四、那为什么不全用 RPC?HTTP/REST 的不可替代
既然 RPC 更快,为什么对外 API 几乎都用 HTTP/REST?因为通用性和生态:
- 跨语言、跨平台、跨组织:HTTP + JSON 是事实标准,任何语言、任何客户端、任何第三方都能轻松调用。RPC 框架的二进制协议往往绑定特定框架/语言生态,对方也得用配套的东西。
- 浏览器友好:网页前端只能发 HTTP,调不了 Dubbo 那种自定义协议。
- 可读易调试:JSON 人能看懂,可以用浏览器、curl、Postman 直接测;二进制 RPC 报文抓包看不懂,调试门槛高。
- 穿透性好:HTTP 走 80/443,防火墙、代理、网关都天然支持;自定义协议可能被中间设施拦。
- 无强耦合:REST 靠 URL + JSON 弱约定,双方独立演进;RPC 常需共享接口定义(IDL/jar),耦合更紧。
五、结论:分场景选,不是二选一
成熟架构往往两者并存:
- 对内、服务间高频调用 → RPC 框架(Dubbo/gRPC)。追求性能、强类型、内置服务治理。
- 对外、开放给第三方 / 浏览器 / 移动端 → HTTP/REST(或 GraphQL)。追求通用、易调试、生态广。
典型形态:外部请求经 API 网关(HTTP/REST) 进来,网关内部再用 RPC 调各个微服务。各取所长。
六、常见误区与追问
| 考点 | 正确口径 |
|---|---|
| RPC | 像调用本地函数一样调用远程服务,强调方法和参数 |
| HTTP/REST | 围绕资源和统一接口,强调 URL、方法、状态码 |
| 关系 | RPC 可以基于 HTTP,也可以基于 TCP、HTTP/2 等 |
RPC: UserService.GetUser(id=1)
REST: GET /users/1
RPC over HTTP/2: gRPC
REST over HTTP/1.1 or HTTP/2
RPC 和 HTTP 不是同一维度:RPC 是调用风格,HTTP 是应用层协议,二者可以组合。
- 误区:RPC 一定不用 HTTP。 gRPC 就基于 HTTP/2,很多 JSON-RPC 也可走 HTTP。
- 误区:REST 一定比 RPC 慢。 性能取决于协议栈、序列化、连接复用、实现和业务处理,不是风格本身决定。
- 误区:RPC 只能内部用,HTTP 只能外部用。 这是常见实践偏好,不是硬性限制;关键看契约、治理和兼容需求。
- 追问:RPC 的优势是什么? 强契约、代码生成、调用体验接近本地方法,适合内部服务治理。
- 追问:REST 的优势是什么? 基于通用 HTTP 语义,易调试、易缓存、生态广,适合开放 API。
- 追问:如何选择? 内部高性能强契约可选 RPC,对外开放和资源型接口多选 HTTP/REST。
七、加强记忆
层次要分清:HTTP 是应用层协议,RPC 是**「像调本地方法一样调远程」的思想**,RPC 框架可基于 HTTP(gRPC=HTTP/2)也可用自定义 TCP。面试真正比的是「RPC 框架(Dubbo/gRPC,二进制序列化 + 精简协议 + 内置服务治理)」vs「REST/HTTP(JSON 文本、通用、浏览器友好、易调试)」。RPC 快(体积小编解码快,内部高频调用优势大);REST 通用(跨语言、可读、生态广)。结论:对内微服务用 RPC,对外开放 API 用 HTTP/REST,成熟架构两者并存、网关衔接。