Dubbo 和 Feign 有什么区别?

#Java#面试八股

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. 核心差异

维度DubboOpenFeign
协议Dubbo 协议(TCP 长连接)HTTP/1.1(可配 HTTP/2)
序列化Hessian2(默认)/ Protobuf / JSONJSON(Jackson)
性能高,头部开销小、序列化紧凑中,文本协议 + JSON
服务治理内建:路由、权重、超时、重试、熔断依赖 Spring Cloud 生态组合
跨语言Dubbo 3 支持 Triple/gRPC 后可跨语言天然跨语言
调试需要 Telnet/管理台/泛化调用curl 即可复现
侵入性需要接口 jar 共享(或泛化调用)接口 + 注解,侵入小
注册中心Nacos / ZooKeeperNacos / 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。把两者当成互斥选项是误解,真实系统里它们经常按链路分工共存。

笔记加载中…