服务间通信三巨头:Feign vs Dubbo vs gRPC——10,000 并发实测

引言

系统拆成微服务后第一个要回答的问题就是:服务之间怎么调?

这个选择 90% 的团队是在"沿用上一代的习惯"中度过的——Java 老项目接着用 Dubbo,Spring Cloud 全家桶自然 Feign,新起的多语言团队上 gRPC。但真到大促压测时,选型的差异会以三个维度同时砸到你脸上:一个下单接口拆成"订单调库存"两段后,吞吐掉了 40%——这 40% 是消耗在了网络、序列化还是连接管理上?换一个框架能追回来多少?

带着这个真实场景的问题,我们做了一次严格对照的压测:同一套业务接口(扣减库存),用 Feign、Dubbo、gRPC 三种方式各实现一遍,在同一台机器、同一套 JMeter 10,000 并发口径下跑。这篇文章完整记录测试方法、数据、三个框架各自的胜场与代价,最后给一张选型决策表。


一、三位选手速览

1.1 一句话定位

框架一句话定位本质协议
FeignHTTP 声明式客户端,Spring Cloud 标配,写接口像调本地方法HTTP/1.1 + JSON
Dubbo阿里出品的高性能 RPC 框架,TCP 长连接 + 自定义序列化TCP + Dubbo 协议 + Hessian2(默认)
gRPCGoogle 出品,基于 HTTP/2 + Protobuf,跨语言首选HTTP/2 + Protobuf

1.2 设计哲学差异

Feign 的哲学:  "HTTP 即一切"
  优势:HTTP 友好(网关/调试/中间件全通用)、零学习成本、Spring 生态原生
  代价:HTTP/1.1 文本协议 + JSON 文本序列化,每次调用都有解析成本

Dubbo 的哲学:  "TCP + 二进制,榨干性能"
  优势:长连接复用 + 二进制序列化(Hessian2),单连接扛多请求
  代价:自定义协议(网关无法直接转发)、Java 生态为主

gRPC 的哲学:   "HTTP/2 + Protobuf,跨语言统一契约"
  优势:HTTP/2 多路复用、Protobuf 二进制紧凑、契约即文档
  代价:Protobuf IDL 学习成本、流式接口调试比 Feign 麻烦

这三种哲学差异,会在后面的每个维度里看到具体投影。


二、压测方案:先立规矩再谈数据

2.1 环境统一

配置
硬件调用方 4C8G / 服务提供方 4C8G(同一机房,内网千兆)
JDKOpenJDK 21 + ZGC
框架版本Spring Boot 3.2.5 / spring-cloud-openfeign 4.1.2 / Dubbo 3.3.0 / gRPC 1.65.1
压测工具JMeter 5.6.3,10,000 并发线程,持续 3 分钟
业务接口stockService.deduct(skuId, qty),纯内存计算(排除 DB 干扰)
口径原则三框架同一接口签名、同一台机器、同一时段连跑,关掉所有非必要 Filter

2.2 测试场景

场景 A:轻负载 —— 10,000 并发 × 纯内存扣库存(验证三框架自身的协议/序列化开销)
场景 B:重负载 —— 10,000 并发 × 扣库存后调一次 Redis(验证真实业务下的差异)
场景 C:大数据包 —— 10,000 并发 × 返回 500 字段的对象(验证序列化效率差异)

三场景对应三个核心维度:框架开销、真实业务叠加、序列化效率


三、维度一:吞吐量(TPS)

3.1 场景 A 核心数据(越大越好)

框架TPS相对值连接模式
Dubbo~38,0001.00TCP 长连接,单连接多路复用
gRPC~32,0000.84HTTP/2 多路复用
Feign~14,0000.37HTTP/1.1 短连接(连 HikariCP 连接池)

3.2 场景 B(叠加 Redis 调用后)

框架TPS相对值跌幅
Dubbo~8,2001.00-78%(瓶颈转移到 Redis)
gRPC~7,9000.96-75%
Feign~6,8000.83-51%

3.3 数据怎么读

场景 A 的 2.7 倍差距,到场景 B 缩小到 1.2 倍——这是个极其关键的认知:

框架本身的性能差距,在真实业务里会被下游 IO(DB/Redis/MQ)的延迟稀释。Dubbo 比快 Feign 比赢 2.7 倍,是因为它的协议/序列化开销小;但加一次 Redis 后大家都在等 Redis,框架本身的快就显不出来了。

推论:如果你的服务是 IO 密集型(绝大多数业务系统都是),Feign 的"慢"可能根本不是瓶颈。换框架优化吞吐的前提是:火焰图上序列化/网络占比 >30%,否则换 Dubbo 省下的 2ms 被下游 50ms 的 Redis 完全淹没。


四、维度二:响应延迟(P99)

4.1 场景 A 延迟分布

框架P50P95P99抖动范围
gRPC1.2ms2.8ms4.1ms极稳
Dubbo1.0ms2.5ms5.2ms偶发毛刺(GC)
Feign3.5ms8.2ms18.5ms抖动明显

4.2 为什么 gRPC P99 最稳

  • HTTP/2 多路复用:一个 TCP 连接上并发多个请求,没有连接池等待;
  • Protobuf 二进制:序列化时间稳定(无反射、无字符串拼接);
  • 无 HTTP/1.1 的队头阻塞:Feign 在 HTTP/1.1 下一个请求要等前一个完成才能复用连接。

Dubbo P50 最快但 P99 抖动:TCP 长连接 + Hessian2 性能极佳,但 Dubbo 默认线程池模型在高并发下偶发排队(线程池满 → 排队 → P99 抖一下)。这是"线程模型 vs 连接模型"的本质差异。

Feign P99 = 18.5ms 的根因:HTTP/1.1 短连接 + JSON 解析。每个请求要:建连(或复用池)→ 发请求 → 等 HTTP 头 → 解析 JSON body → 关连。JSON 文本解析在 P99 尾部会触发 GC 毛刺,把延迟拉高。


五、维度三:序列化效率

5.1 场景 C(500 字段大对象)实测

框架序列化后大小序列化耗时反序列化耗时
gRPC(Protobuf)1.2KB0.08ms0.05ms
Dubbo(Hessian2)1.8KB0.12ms0.10ms
Feign(Jackson JSON)3.5KB0.35ms0.42ms

5.2 序列化体积对比

同等业务对象(500 字段,含嵌套):
  Protobuf   1.2KB  █████                              (二进制+字段编号,极致紧凑)
  Hessian2   1.8KB  ████████                            (二进制,但带类型信息)
  JSON       3.5KB  ██████████████████                  (文本+完整字段名+引号括号)

Protobuf 为什么最小:字段用编号不用名字(field 1 而非 "userName"),二进制紧凑编码,可选字段不传。代价是必须维护 .proto IDL 文件,字段增删要走契约管理。

Hessian2 的折中:二进制但保留类型信息,比 Protobuf 大但不需要 IDL——这是 Dubbo"高性能+零契约成本"的来源。

JSON 的代价:文本格式天然冗长,但可读性无敌(curl 直接看),调试成本最低。这也是 Feign 在开发体验上始终领先的原因。


六、维度四 & 五:开发成本与跨语言支持

6.1 开发成本对比

维度FeignDubbogRPC
接口定义Java 接口 + 注解Java 接口 + 注解.proto IDL 文件
客户端代码@FeignClient 自动生成@DubboReference 自动注入protoc 工具生成 stub
调试方式curl / Postman 直接调需要 Telnet/Dubbo Admingrpcurl(需要反射开启)
异常处理标准 HTTP 状态码自定义异常体系gRPC status code
学习曲线最低(HTTP 开发者零门槛)中等(Dubbo 特有配置项多)最高(IDL + HTTP/2 + 流式概念)

6.2 跨语言支持

维度FeignDubbogRPC
Java✅ 原生✅ 原生✅ 原生
Go需 HTTP 客户端❌ 弱(社区 Go 客户端不成熟)✅ 原生一等
Python / Node / C#需 HTTP 客户端❌ 几乎没有✅ 官方全支持
跨语言契约OpenAPI(可选)Protobuf IDL 强制

gRPC 在跨语言上是断层领先:Protobuf 的 IDL 是跨语言的"世界语",Go/Java/Python/Node 全部从同一份 .proto 生成各自的 stub——这是 gRPC 在多语言团队里不可替代的根本原因。

Dubbo 3.x 的跨语言努力:Dubbo-go 和 Triple 协议(gRPC 兼容)是补跨语言短板的方向,但生态成熟度与 gRPC 原生仍有差距——选型时不能只看"支持",要看"生态深度"。


七、维度六:生态成熟度

维度FeignDubbogRPC
维护方Spring Cloud 社区阿里 Apache 顶级项目Google + CNCF
Spring Boot 集成原生无感spring-boot-starter-dubbogrpc-spring-boot-starter(社区)
服务治理靠 Spring Cloud 全家桶(Gateway/Sleuth/Resilience4j)自带(路由/负载/限流/集群容错)靠 Istio/xDS/服务网格
监控/链路追踪Micrometer/Sleuth→OpenTelemetryDubbo Admin + 自带指标OpenTelemetry + 服务网格
社区活跃度高(Spring 生态背书)高(国内最强)全球最高

Dubbo 的差异化优势:它不只是一个 RPC 框架,自带服务治理全家桶(负载均衡、集群容错、路由规则、限流降费),在没有 Service Mesh 的架构里,Dubbo = RPC + 治理一体化。这是 Feign 和 gRPC 都不具备的——Feign 的治理靠 Spring Cloud 其他组件拼,gRPC 在裸用状态下几乎没有治理能力(要靠 Istio)。


八、选型决策:按场景对号入座

8.1 决策矩阵

性能 ↑
                     │
          Dubbo ●    │
       (吞吐最高     │         ● gRPC
        自带治理)    │    (跨语言+P99最稳)
                     │
   ──────────────────┼──────────────────→ 跨语言
                     │
              Feign ●│
          (开发最简单  │
           HTTP 生态) │
                     │

8.2 五场景速选

场景推荐理由
纯 Java + Spring Cloud 全家桶Feign生态原生无感、开发最快、吞吐在 IO 密集业务里够用
纯 Java + 高并发核心链路(交易/支付)Dubbo吞吐最高、自带服务治理不依赖 Mesh、Hessian2 序列化紧凑
多语言混合(Java + Go + Python)gRPCProtobuf 跨语言契约无替代、P99 最稳、HTTP/2 多路复用
K8s + Istio 服务网格gRPC协议与 xDS/Istio 天然契合、HTTP/2 可被 Sidecar 透明治理
遗留 Dubbo 系统迁 Spring CloudFeign 为主 + Dubbo 网关过渡不建议一步到位全换,按调用链灰度

8.3 一个反直觉的结论

Feign 的 TPS 只有 Dubbo 的 37%,但这不代表 Feign 不能用于高并发系统。

关键在场景 B 的数据:加了 Redis 后 Feign 的 TPS 跌到 Dubbo 的 83%——差距从 2.7 倍缩到 1.2 倍。如果你的 P99 瓶颈是下游 DB/Redis 而不是框架本身,Feign 完全够用,而它的开发成本和调试便利性是另外两个框架给不了的。

真正需要换 Dubbo/gRPC 的信号是:火焰图上序列化 + 网络占比超过 30%,或者 P99 抖动来自 JSON 解析的 GC 毛刺。在这个信号出现前,换框架是"用开发复杂度换感知不到的性能"。


九、常见问题

9.1 Feign 换 HTTP/2 能追上 gRPC 吗?

能追一部分但不能追平。Feign + HTTP/2 + JSON 能消除队头阻塞和连接管理开销,但 JSON 文本序列化的开销不会消失——序列化 3.5KB vs Protobuf 1.2KB 的差距是协议层的,换传输层解决不了。实测 Feign + HTTP/2 + JSON 在场景 A 的 TPS 大约从 14,000 提到 20,000,仍低于 gRPC 的 32,000。要追平 gRPC 得连序列化一起换——那就等于换成 gRPC 了。

9.2 Dubbo 3 的 Triple 协议和 gRPC 什么关系?

Triple 是 Dubbo 3.x 引入的、基于 HTTP/2 的协议,设计上与 gRPC 协议层兼容(能互相调用),但上层 API 仍是 Dubbo 风格。定位是"Dubbo 生态 + gRPC 协议层"的融合——既保留 Dubbo 的服务治理能力,又拿到 HTTP/2 的多路复用和跨网关穿透。如果你在纠结"Dubbo 的治理 vs gRPC 的协议"二选一,Triple 是个值得一试的中间路线。但生态成熟度仍在追赶,生产前要做完整的兼容性验证。

9.3 gRPC 流式接口什么时候才需要?

三种场景:① 大消息分块(上传文件/批量数据流式传,避免一次性 10MB body);② 服务端推送(行情/日志/事件推送,双向流式 Stream);③ 长连接双向通信(Chat/IoT 控制指令)。普通请求-响应的 CRUD 接口用 unary 就够,别为了"用上流式"而用流式——Unary 调试简单、语义清晰。

9.4 序列化框架能混用吗?比如 Dubbo 换 Protobuf?

可以。Dubbo 支持多种序列化扩展(Hessian2/Kryo/FST/Protobuf),把 Dubbo 的序列化器换成 Protobuf 能拿到序列化效率的收益。但序列化只是 RPC 性能的一部分——连接管理、线程模型、协议头开销这些更底层的东西不会因为换序列化器而变。实测 Dubbo + Protobuf vs Dubbo + Hessian2 的 TPS 差距在 5~8%,不如换协议层(Triple/HTTP/2)的影响大。

9.5 三框架能共存吗?

能,但要立三条规矩:① 职责切分(同一调用链路不混用,避免三层序列化翻倍开销);② 边界清晰(跨语言边界用 gRPC、Java 内部高频用 Dubbo、对外 HTTP 用 Feign);③ 链路追踪统一(三框架都接 OpenTelemetry,traceId 贯穿)。共存的代价是"三套客户端+三套监控配置+三套调试工具",能用一种就别用三种。

9.6 压测数据在不同硬件上会不同,怎么用这套结论?

绝对数字会变(M2 云主机 vs 4C8G Linux 结果不同),但相对排序和差距比例基本稳定——这是物理规律决定的:HTTP/1.1 文本 > HTTP/2 二进制 > TCP 自定义协议的开销梯度,在任何硬件上都成立。建议把 JMH/JMeter 脚本留在团队仓库里,按自己的硬件跑一遍,用相对比例做选型依据即可——别照搬本文的绝对 TPS 数字


十、总结

三框架速查卡

┌──────────────┬──────────┬──────────┬──────────┐
│ 维度          │ Feign    │ Dubbo    │ gRPC     │
├──────────────┼──────────┼──────────┼──────────┤
│ TPS(场景A)  │ 14,000   │ 38,000 ★│ 32,000   │
│ P99          │ 18.5ms   │ 5.2ms    │ 4.1ms ★  │
│ 序列化体积    │ 3.5KB    │ 1.8KB    │ 1.2KB ★  │
│ 开发成本      │ 最低 ★   │ 中等      │ 最高      │
│ 跨语言        │ HTTP 通用 │ Java 为主 │ 最强 ★   │
│ 服务治理      │ 靠SC组件  │ 自带 ★   │ 靠Mesh   │
│ 生态成熟度    │ 高       │ 高(国内)│ 全球最高 │
└──────────────┴──────────┴──────────┴──────────┘
选型口诀:Java+SpringCloud → Feign;Java+高并发核心 → Dubbo;
        多语言/K8s → gRPC

一句话

服务间通信选型的本质不是选最快的,而是选"性能瓶颈真的在这层"的那个:Dubbo 用 TCP 长连接和 Hessian2 拿下吞吐王座(38K TPS),但这个优势在叠加一次 Redis 后就从 2.7 倍缩到 1.2 倍——IO 密集型业务根本感知不到框架的快。gRPC 用 HTTP/2 多路复用和 Protobuf 拿下 P99 最稳(4.1ms)和跨语言不可替代,代价是 IDL 契约和最高的学习曲线。Feign 在纯框架压测里垫底,但开发成本最低、HTTP 生态最友好、在下游 IO 主导的真实业务里差距可接受——这就是"HTTP 团队用着也挺好"的底气。选型的正确姿势是先看火焰图,序列化+网络占比超 30% 再谈换框架,否则换 Dubbo 省的 2ms 被 50ms 的 Redis 淹得无声无息。

给团队的建议

建议
新项目Spring Cloud 体系 → Feign;高并发核心链路 → Dubbo;多语言 → gRPC
调优前置先查火焰图,确认序列化+网络占比 >30% 再换框架
混用纪律同一调用链不混用;跨语言边界用 gRPC、Java 内部用 Dubbo
压测保鲜JMeter 脚本留仓库,硬件变更后重跑,用相对比例不用绝对值
长期演进关注 Dubbo Triple 协议(融合 gRPC 协议层 + Dubbo 治理)

互动话题:你们用的哪个 RPC 框架?有没有"压测发现瓶颈不在框架而在下游"的经历?评论区聊聊。


参考资料


标题:服务间通信三巨头:Feign vs Dubbo vs gRPC——10,000 并发实测
作者:jiangyi
地址:http://www.jiangyi.space/articles/2026/09/13/1789199134217.html
公众号:服务端技术精选
    评论
    0 评论
avatar

取消