Dubbo 和 Feign 有什么区别?
结论先行:Dubbo 是基于 TCP 的 RPC 框架,自带服务治理(注册、路由、负载均衡、熔断),性能高、侵入性中等;Feign(OpenFeign)是声明式 HTTP 客户端,把接口注解翻译成 HTTP 请求,天然跨语言、易调试,但序列化与协议开销大。二者不是同一层的东西,Dubbo 是完整 RPC 体系,Feign 是 HTTP 调用的一层封装。
1. 调用链路对比
Dubbo:
consumer ── Dubbo 协议(自定义二进制头 + Hessian2/Protobuf 序列化)──▶ provider
注册中心(Nacos/ZK)提供地址列表,consumer 本地做负载均衡与路由
Feign:
consumer ── HTTP/1.1 + JSON ──▶ 服务发现(lb://)──▶ provider
每次调用:编码请求体 → 建连接/复用连接 → 解析 JSON → 反序列化
Dubbo 默认长连接、单一 TCP 连接上多路复用请求;Feign 走 HTTP,依赖连接池(Apache HttpClient / OkHttp)才能复用。
2. 核心差异
| 维度 | Dubbo | OpenFeign |
|---|---|---|
| 协议 | Dubbo 协议(TCP 长连接) | HTTP/1.1(可配 HTTP/2) |
| 序列化 | Hessian2(默认)/ Protobuf / JSON | JSON(Jackson) |
| 性能 | 高,头部开销小、序列化紧凑 | 中,文本协议 + JSON |
| 服务治理 | 内建:路由、权重、超时、重试、熔断 | 依赖 Spring Cloud 生态组合 |
| 跨语言 | Dubbo 3 支持 Triple/gRPC 后可跨语言 | 天然跨语言 |
| 调试 | 需要 Telnet/管理台/泛化调用 | curl 即可复现 |
| 侵入性 | 需要接口 jar 共享(或泛化调用) | 接口 + 注解,侵入小 |
| 注册中心 | Nacos / ZooKeeper | Nacos / Eureka / Consul |
| 适用 | 内部高性能、强类型、Java 为主 | 对外 API、多语言、快速迭代 |
3. 代码对照
Dubbo(Spring Cloud Alibaba 体系):
// 接口单独打成 api jar,provider 与 consumer 共享
public interface StockService {
StockDTO getStock(Long skuId);
}
@DubboService(version = "1.0.0", timeout = 2000)
public class StockServiceImpl implements StockService {
@Override
public StockDTO getStock(Long skuId) {
return new StockDTO(skuId, 100);
}
}
@DubboReference(version = "1.0.0", check = false)
private StockService stockService; // 像本地方法一样调用
OpenFeign:
@FeignClient(name = "stock-service", path = "/stock")
public interface StockClient {
@GetMapping("/{skuId}")
StockDTO getStock(@PathVariable("skuId") Long skuId);
}
spring:
cloud:
openfeign:
client:
config:
default:
connect-timeout: 1000
read-timeout: 2000
logger-level: basic
4. 什么时候选哪个
| 场景 | 建议 |
|---|---|
| 内部服务、QPS 高、延迟敏感 | Dubbo(或 gRPC) |
| 需要对外暴露、多语言客户端 | HTTP + OpenFeign / REST |
| 团队以 Spring Cloud 为主、追求开发效率 | OpenFeign |
| 已有 Dubbo 体系、需要平滑演进 | Dubbo 3 + Triple 协议(兼容 gRPC) |
| 强类型契约、接口变更需编译期发现 | Dubbo(共享 api jar) |
一个常见误区是「HTTP 一定比 RPC 慢所以不能用」:在局域网内,JSON 序列化与 HTTP 头的开销通常在几十微秒级,真正的瓶颈往往是业务逻辑与数据库。除非压测证明通信是瓶颈,否则不必为性能强行上 RPC。
5. 混用与互通
- Dubbo 3 的 Triple 协议基于 HTTP/2,可被 gRPC 客户端调用,也能穿过网关(Gateway 支持 Dubbo 转发插件)。
- Feign 调 Dubbo 服务:给 Dubbo 服务再暴露一层 HTTP 接口,或使用网关协议转换,不推荐在 Feign 里手写 Dubbo 协议。
- 同一系统内混用很常见:核心交易链路 Dubbo,运营后台 Feign。
6. 常见追问
追问一:Dubbo 一定比 Feign 快吗? 单看协议与序列化,是的。但 Feign 配好连接池、开启压缩、减少大对象传输后,差距会缩小到业务可接受范围。压测数据要看具体报文大小。
追问二:Feign 支持长连接吗?
支持。底层用 Apache HttpClient 或 OkHttp 的连接池,默认 keep-alive。若用 JDK 的 HttpURLConnection 且未配置,可能每次新建连接。
追问三:Dubbo 的服务发现和 Feign 一样吗?
思路一致:注册中心 + 本地缓存 + 负载均衡。区别在 Dubbo 有更丰富的路由规则(标签路由、条件路由、权重),Feign 侧靠 LoadBalancer + 自定义策略。
追问四:为什么 Dubbo 要共享接口 jar? 因为它是「接口级 RPC」:consumer 需要接口的字节码来生成代理、确定方法签名与序列化类型。Feign 只需要 URL 与方法签名,契约靠 HTTP 文档约定。
追问五:Spring Cloud Alibaba 里 Feign 和 Dubbo 能同时用吗? 能,二者依赖不同、互不冲突。但要注意注册中心共用 Nacos 时的命名空间与服务名隔离,避免误调。
小结
选型的分水岭是通信边界:内部、Java 同构、性能敏感 → Dubbo/gRPC;对外、多语言、可调试优先 → OpenFeign/HTTP。把两者当成互斥选项是误解,真实系统里它们经常按链路分工共存。