dubbo和oppenFeign是如何找到正确的url请求地址的

dubbo和oppenFeign是如何找到正确的url请求地址的

这个问题本质是在问一句话:

动态代理只是入口,真正“找到 URL/地址”的是“服务发现 + 本地缓存 + 负载均衡”。

Dubbo 和 OpenFeign 都是“代理 + 路由系统”,但实现路径不一样。


一、核心结论(先记住)

Dubbo: 注册中心 → 订阅服务 → 本地Invoker列表 → 负载均衡选地址 → 发RPC Feign: 注册中心 → 获取服务实例列表 → LoadBalancer选实例 → 拼HTTP URL → 发请求

二、Dubbo 是怎么找到地址的?

1. 启动阶段:先“拿到所有Provider地址”

Provider注册

UserService → 10.1.1.10:20880 → 10.1.1.11:20880 → 10.1.1.12:20880

注册中心:

  • Apache ZooKeeper
  • Nacos

2. Consumer订阅服务

Consumer → 注册中心订阅 UserService

返回:

Invoker列表(关键!!) Invoker = Provider封装对象

3. 本地缓存(重点)

Consumer不会每次都查注册中心,而是:

本地维护: List<Invoker>

例如:

[ Invoker(10.1.1.10:20880), Invoker(10.1.1.11:20880), Invoker(10.1.1.12:20880) ]

4. 动态代理调用时发生什么

userService.queryUser(1L);

进入代理:

InvocationHandler.invoke()

5. 关键步骤:选地址(LoadBalance)

Dubbo核心流程:

Invoker列表 ↓ LoadBalance(负载均衡) ↓ 选一个Invoker ↓ 得到真实地址

例如:

10.1.1.11:20880

6. RPC请求发送

NettyClient → TCP → Provider

Dubbo总结链路

动态代理 ↓ Invoker列表(本地缓存) ↓ LoadBalance ↓ 选出Provider地址 ↓ Netty发送RPC

三、Feign 是怎么找到 URL 的?

Feign本质是:

HTTP客户端 + 服务发现 + 负载均衡

1. 启动阶段:获取服务实例列表

例如:

@FeignClient("user-service")

注册中心返回:

user-service: - 10.1.1.10:8080 - 10.1.1.11:8080

2. 存入本地服务列表

ServiceInstanceListSupplier ↓ 本地缓存

3. 动态代理调用

userClient.get(1L);

进入:

FeignInvocationHandler

4. 关键步骤:选实例(LoadBalancer)

Feign通过:

  • Spring Cloud LoadBalancer
  • 或 Ribbon(旧版本)

流程:

实例列表 ↓ LoadBalancer ↓ 选一个实例

例如:

10.1.1.10:8080

5. 拼接 URL

Feign会根据注解拼URL:

@GetMapping("/user/{id}")

最终变成:

http://10.1.1.10:8080/user/1

6. 发HTTP请求

HttpClient / OkHttp ↓ TCP连接池 ↓ 服务端Controller

Feign总结链路

动态代理 ↓ 服务实例列表(本地缓存) ↓ LoadBalancer ↓ 拼HTTP URL ↓ HTTP请求

四、核心区别(面试重点)

对比点DubboFeign
地址来源Invoker(RPC封装对象)ServiceInstance
路由方式LoadBalance选InvokerLoadBalancer选实例
URL生成不需要URL必须拼HTTP URL
协议TCP + RPCHTTP
本地缓存Invoker列表Instance列表

五、最核心本质(一定要记住)

Dubbo: 找的是 Invoker(RPC对象) 不是URL Feign: 找的是 ServiceInstance 然后拼 URL

六、面试标准答案

可以这样回答:

Dubbo 和 OpenFeign 都是通过动态代理发起调用,但地址解析是在代理之后完成的。

Dubbo 在启动时会从注册中心订阅服务,将 Provider 地址封装成 Invoker 对象缓存到本地。调用时通过动态代理进入 InvocationHandler,然后结合 LoadBalance 从 Invoker 列表中选择一个具体的 Provider,直接通过 Netty 发起 RPC 调用,不依赖 URL。

OpenFeign 则是在启动时从注册中心获取服务实例列表,缓存为 ServiceInstance。调用时通过动态代理进入 FeignHandler,再通过 Spring Cloud LoadBalancer 选择一个实例,然后根据接口注解(如 @GetMapping)拼接成完整 HTTP URL,再发起 HTTP 请求。


一句话总结

Dubbo:代理 → 选Invoker → RPC直连 Feign:代理 → 选实例 → 拼URL → HTTP请求