为什么很多团队的内部 API,早就不该只用 REST 了
服务越写越多,接口越写越拧巴。明明是 approveInvoice() 这种动作,却要硬拗成 POST /invoices/{id}/approval。很多团队的问题,不是不会做 API,而是一开始就把内部系统也按公共 API 那套方式设计了。
服务越写越多,接口越写越拧巴。
明明是 approveInvoice() 这种动作,却要硬拗成 POST /invoices/{id}/approval。
文档越来越厚,新来的同事越看越迷糊——这到底是资源操作,还是动作调用?
很多团队的问题,不是不会做 API,而是一开始就把内部系统也按公共 API 那套方式设计了。
为什么很多人听过 RPC,但一直没真正理解它
RPC 这个词,做后端的几乎都听过。gRPC、Thrift、Dubbo……名字都能报一串,但真要问"RPC 到底是什么",很多人会卡在一句"就是远程调用呗",然后就说不下去了。
RPC 的全称是 Remote Procedure Call,中文叫"远程过程调用"。但这句话本身没什么信息量。
RPC 的价值,不是把请求发到远端,而是把远端调用变得像本地函数一样顺手。
你写一个函数调用,不用关心它是在本机还是在另一台机器上;你传参、返回值,不用手动拼 JSON、不用琢磨 HTTP 状态码、不用猜对方到底期望什么字段。RPC 框架帮你把序列化、网络传输、反序列化这些事都包起来了。
REST 和 RPC 的根本差异,也不只是协议层。REST 更像资源操作模型,RPC 更像动作调用模型。REST 围绕"资源"建模,用 GET、POST、PUT、DELETE 去操作;RPC 围绕"方法"建模,直接定义输入和输出。
很多人一直没理解 RPC,是因为他们只记住了"更快"这个标签,但没意识到它真正改变的是接口抽象方式。
为什么内部系统继续死守 REST,会越来越别扭
REST 对于公共 API 来说,确实很直观。资源清晰、动词统一、用 curl 或 Postman 一测就明白。第三方集成、开放平台、需要人类直接调试的场景,REST 都是合理选择。
但到了内部服务通信,事情就开始变味了。
想象一下这些接口:
approveInvoice(审批发票)calculateRiskScore(计算风险分)triggerReconciliation(触发对账)
这些事情本质是"执行动作",不是"操作资源"。如果硬塞进 REST,往往会写成这样:
POST /invoices/{id}/approval
POST /risk-scores/calculate
POST /reconciliations/trigger
看上去也不是不能工作,但越写越别扭。你得给每个动作想一个资源名词,得解释为什么这个 POST 不是创建资源而是执行逻辑,得在文档里额外说明"这个端点实际上不做 CRUD,只是触发一个流程"。
时间一长,接口文档里会堆满这种"伪资源"。新来的同事看一遍,根本分不清哪些是真正的资源操作,哪些是硬拗成 REST 的动作调用。
内部系统真正缺的,往往不是一个更快的协议,而是一套更稳的协作契约。
RPC 真正比 REST 强的地方,不只是快
说到 RPC 的优势,很多人第一反应是"性能更好"。这没错,但不完整。
gRPC 用 Protocol Buffers 这类二进制格式,确实比 JSON 更紧凑,序列化和反序列化更快,网络延迟和带宽开销更低。再加上 HTTP/2 的多路复用、头部压缩、长连接通信,高频调用场景下优势明显。
但性能只是表层。RPC 真正赢的,是一整套工程秩序。
强类型契约
在 gRPC 里,接口契约用 .proto 文件定义。字段名、类型、哪些可选、哪些必填、字段编号怎么保证兼容性,都写得清清楚楚。
客户端和服务端都基于同一份契约生成代码。你改一个字段,编译阶段就能发现问题,不用等到运行时才报错。
这对 Go、Java、Rust 这类强类型语言的开发体验尤其友好。接口不再是"文档里写的",而是"编译器帮你验证的"。
代码生成和协作一致性
RPC 框架通常自带多语言代码生成。服务端定义好接口,客户端代码自动生成。不同团队、不同语言、不同版本之间,不容易出现"你以为我返回这个字段,其实我早就改了"这种问题。
REST 也能通过 OpenAPI / Swagger 生成代码,但很多项目里仍然是半自动甚至手写。schema 约束更松,文档和真实返回结果慢慢漂移,最后没人敢确定哪份是准的。
版本演进更可控
基于 Protocol Buffers 的 RPC,在保持字段编号稳定、正确使用可选字段的前提下,可以平滑地新增字段、兼容老客户端。
REST 的版本管理则常常比较混乱。URL 路径里堆 /v1、/v2,JSON 字段在不同版本里不一致,文档更新跟不上代码变更。对于频繁发布、依赖紧密的微服务体系,这种松散会带来持续的协作成本。
流式通信能力
gRPC 原生支持客户端流、服务端流和双向流。实时更新、状态推送、进度回传这类场景,用 gRPC 可以很自然地实现。
REST over HTTP/1.1 在高频调用场景里会有更多请求开销,而且不擅长双向持续通信。虽然 HTTP/2 和 WebSocket 能补一部分,但终究不是原生设计。
REST 没有过时,它只是更适合另一类系统
写到这儿,得给 REST 一个公平的位置。
RPC 并不是所有场景都更好。如果面对的是:
- 公共 API
- 第三方集成
- 语言、平台、团队边界都很松的系统
- 需要人类直接读、直接测、直接调的接口
那么 REST 仍然有非常明显的优势:更通用、更易理解、更容易用 curl 或 Postman 直接测试、不需要额外共享 IDL。
不是 REST 过时了,而是很多内部服务通信根本不该只按 REST 去设计。
真正的选型问题,不是"REST 和 RPC 谁先进",而是"你的场景需要什么样的契约、性能和通信方式"。
什么时候该认真考虑 RPC
如果你的系统具备这些特征,就该认真考虑 RPC:
- 内部 API 很多,微服务之间调用频繁
- 需要严格契约,不能容忍接口漂移
- 需要高吞吐、低延迟
- 需要 streaming、retry、deadline 等高级能力
- 对可观测性、安全性、扩展性要求高
- 团队协作成本已经因为接口松散而上升
反过来,如果你做的是开放平台、第三方集成、需要人类直接调试的接口,REST 依然是合理选择。
REST 不是错,问题是很多团队把它用到了它并不顺手的地方。