一句话先把问题摆出来
服务之间应该用 HTTP 还是 RPC 通信?
这是任何一个 Java 微服务团队都绕不过去的选择。社区里两套生态各有铁粉:
- Spring Cloud + OpenFeign:基于 HTTP/REST,整套 Spring 全家桶最自然的延伸
- Apache Dubbo:阿里开源的 RPC 框架,国内大厂的事实标准
新人选型时常常陷入一个误区——纠结于"谁性能好"。但只看 QPS 这件事会让你错过更重要的因素:协议哲学、生态契合度、运维成本、组织能力。
本文把这两套方案的差异、各自优劣、以及不同场景下的选型建议讲清楚。
协议层:HTTP 与 RPC 的本质差异
OpenFeign:HTTP 客户端的"声明式"
Feign 的本质是对 HTTP 客户端的封装。你定义一个接口,加几个注解,Feign 用动态代理把方法调用翻译成 HTTP 请求:
| |
调用方写起来像调本地方法:
| |
但底层走的是标准 HTTP——序列化通常是 JSON,传输是文本,每次请求都有完整的 HTTP 头开销。所以 Feign 的本质就是一个"会的协议"被打包成"省心的姿势"。
Dubbo:原生 RPC
Dubbo 是为 RPC 而生的。客户端和服务端都是 Java,直接通过自定义的二进制协议(Dubbo 协议、Triple 协议等)传输 Java 对象。
| |
注意——两端共享同一个接口(Java interface),通过注册中心拉到地址后建立长连接。没有 URL,没有 HTTP 头,序列化默认是 Hessian 或 Kryo(紧凑二进制)。
性能差距:到底差多少
实测数据(同机房、千兆内网、相同业务复杂度):
| 指标 | OpenFeign + Spring Cloud | Dubbo(默认 dubbo 协议) |
|---|---|---|
| 单次 RTT | 5-15 ms | 1-3 ms |
| 序列化大小 | JSON,相对大 | Hessian/Kryo,2-5 倍小 |
| 单连接 QPS | 数千 | 数万 |
| CPU 序列化开销 | 较高 | 较低 |
Dubbo 在性能上确实有显著优势——但请注意三点:
- 上述差距在"调用频率高、链路深"时才显著放大;多数业务一次接口调用 50-100ms,5ms 和 1ms 的差距完全淹没在业务里
- Feign 改用 HTTP/2 + Protobuf 就能逼近 RPC 性能(Spring 6 / Spring Cloud 2022+ 支持)
- 性能问题大多在数据库、外部 API、缓存上,通信协议很少是瓶颈
不建议把『性能』当成选 Dubbo 的唯一理由。 如果你不能拿出一个真实的、被 Profiler 证实的、序列化耗时占主导的瓶颈,那性能差距对你来说几乎没意义。
生态契合度:谁配谁更顺手
| 维度 | Spring Cloud + Feign | Dubbo |
|---|---|---|
| 注册中心 | Eureka / Nacos / Consul | Zookeeper / Nacos |
| 配置中心 | Spring Cloud Config / Nacos | Apollo / Nacos |
| 网关 | Spring Cloud Gateway | 通常前置 Nginx + 业务网关 |
| 熔断 | Resilience4j / Sentinel | Sentinel(原生集成) |
| 链路追踪 | Sleuth + Zipkin | Skywalking / 自建 Filter |
| 服务治理 | 基础 | 强(路由、灰度、限流、调度都内置) |
| 跨语言 | 天然 ✓(HTTP) | △(Triple 协议支持,gRPC 互通) |
| 调试工具 | Postman / curl 直接打 | Telnet / Dubbo Admin |
Spring Cloud 的强项是全家桶生态完整,Feign 只是其中一环;Dubbo 的强项是服务治理特性原生且强大——做到 Spring Cloud 同等治理能力,需要拼接一堆组件。
跨语言:被低估的因素
这是很多团队选型时最被低估的因素。
- Feign 走 HTTP/REST:只要对方能发 HTTP 请求,谁都能调。Python、Go、Node 团队对接你的服务零门槛
- Dubbo 默认是 Java-only:跨语言要切到 Triple 协议(基于 gRPC),配置和工具链都比 HTTP 复杂
如果你的组织是多语言团队——前端 Node、数据团队 Python、运营内部系统是 PHP——选 Feign 几乎没有疑问。强行用 Dubbo 让其他语言对接,会成为长期摩擦。
如果你的组织清一色 Java,跨语言不是问题,那 Dubbo 的劣势就消失了。
调试与可观测性
Feign 优势
- HTTP 接口能直接用 Postman / curl 调试
- 浏览器开发工具能看请求响应
- Nginx / 网关日志能直接读
- Tcpdump / Wireshark 抓包能看明文
Dubbo 劣势
- 二进制协议要专用工具(Dubbo Admin、Telnet 命令)
- Mock 和压测要起 Java 客户端
- 排查 “客户端发了什么” 比 HTTP 麻烦得多
| |
可观测性是长期运维的核心痛点——调试方便程度对开发体验的影响远超 5ms 的性能差距。
学习曲线与团队上手成本
| 因素 | Feign | Dubbo |
|---|---|---|
| 新人上手 | 几乎零门槛(懂 HTTP 即可) | 中等(注解 + 注册中心 + 协议) |
| 大团队培训 | 简单 | 中等 |
| 调试体验 | 优 | 中 |
| 扩展定制 | 需懂 OkHttp / RestTemplate | 需懂 Filter / Invoker SPI |
新人入职第一周能用的是 Feign,三周后才能驾驭 Dubbo——团队规模一大,这个差距会成倍放大。
服务治理深度:Dubbo 的硬实力
如果说性能是 Dubbo 被高估的优势,那服务治理才是它真正的护城河。
Dubbo 原生支持的能力清单(Spring Cloud 多数都要拼装实现):
- 多版本并行:
@DubboReference(version = "1.0.0")直接路由到指定版本服务 - 基于条件的路由规则:根据 Header / 参数 / 客户端 IP 路由到不同实例(灰度发布利器)
- 应用级 / 接口级粒度的治理
- 管理后台 Dubbo Admin 可视化调整路由、权重、限流,无需改代码
- 服务分组:环境/业务隔离
这些在 Spring Cloud 体系里要靠 Gateway + 自定义 Filter + Sentinel + Service Mesh 拼出来——能做,但维护成本高。
如果你做的是复杂的内部多团队协作系统(金融、电商核心链路),Dubbo 的治理能力会显著省心。
选型决策树
一些被反复争论的话题
争论 1:Spring Cloud 已经够强,Dubbo 没必要
部分对——如果你的业务复杂度还没碰到治理瓶颈,Spring Cloud 完全够。但有些治理特性(多版本、规则路由)原生 Spring Cloud 真的拼不出 Dubbo 那么顺手。
争论 2:Dubbo 把简单事情复杂化
部分对——Dubbo 的概念多(Provider/Consumer/Registry/Monitor,加上 Filter/Invoker/Cluster),新人确实一脸懵;但一旦上手,业务代码就和 Feign 一样简洁。
争论 3:现在该用 gRPC
gRPC 是个好选择,性能接近 Dubbo,跨语言天然支持。但生态在 Java 圈子相对薄弱——和 Spring 集成、注册中心选型、可观测性都要自己组装。Triple 协议(Dubbo 3)就是兼容 gRPC 的,意图是把"跨语言 + Dubbo 治理"一并拿下。
争论 4:直接用 Service Mesh
Mesh 把通信和治理下沉到 Sidecar,应用层只用最朴素的 HTTP/gRPC。理论上是终极方案,但运维 K8s + Istio 的复杂度让多数中小团队望而却步。
实战建议
我自己在团队里推的一份简版规则:
- 新启动的中小项目:直接 Spring Cloud + Feign。生态完整、上手快、调试方便,性能问题先不要担心
- 已有 Spring Cloud 体系的成熟团队:继续用 Feign,需要更高性能时点对点改 gRPC,不要整体迁 Dubbo
- 大量内部 Java 服务、纯 Java 技术栈、强治理需求:Dubbo(或 Dubbo 3)。多版本、灰度路由这些原生能力会省心
- 有跨语言需求:Feign / gRPC,不要 Dubbo(除非用 Triple)
- 绝不要"大力出奇迹"全家桶迁移:从 Spring Cloud 全部迁到 Dubbo 是高成本低收益的事,点对点重构才是务实做法
| |
混合用没什么问题,只要团队两套都熟。
小结
把全文压成一句话:
OpenFeign 让通信变简单,Dubbo 让治理变强大。多数项目应当从 Feign 开始,治理瓶颈真正出现时再选择性引入 Dubbo——而不是反过来。
性能、生态、跨语言、调试、团队成本是五个真正影响选型的维度。别让"哪个性能好"这个伪问题误导你——通信协议很少是系统瓶颈,能让团队走得远的选择,永远是简单、可调试、生态完整的那一个。