消费者为什么要缓存服务提供者IP

发布时间:2026/6/10 15:05:08

消费者为什么要缓存服务提供者IP 服务发现过程假设有一个服务DubboService public class UserServiceImplProvider启动后向注册中心注册UserService ├── 10.1.1.10:20880 ├── 10.1.1.11:20880 └── 10.1.1.12:20880Consumer启动时DubboReference private UserService userService;会向注册中心订阅UserService注册中心返回10.1.1.10:20880 10.1.1.11:20880 10.1.1.12:20880然后Consumer ↓ 保存到内存形成一个本地服务列表。例如ListInvoker invokers [ provider1, provider2, provider3 ];为什么要缓存到消费者本地如果每次调用都查注册中心userService.queryUser();都变成Consumer ↓ ZooKeeper/Nacos ↓ 获取Provider列表 ↓ Provider那注册中心压力会非常大。Dubbo采用启动时拉取 变更时推送模式。即Consumer ↓ 订阅服务 ↓ 获得Provider列表 ↓ 缓存在本地内存之后调用userService.queryUser();直接本地Invoker列表 ↓ 负载均衡 ↓ 选出Provider ↓ 发起RPC不会再访问注册中心。Provider扩容怎么办例如最开始10.1.1.10 10.1.1.11后来新增10.1.1.12Provider注册到 ZooKeeper。ZooKeeper会通知所有订阅者ConsumerA ConsumerB ConsumerC收到变更事件ChildChangedDubbo更新本地缓存10.1.1.10 10.1.1.11 10.1.1.12整个过程无需重启。注册中心挂了还能调用吗这是面试特别喜欢问的。答案能只要Consumer已经拿到Provider列表那么ZooKeeper挂掉之后userService.queryUser();仍然可以正常调用。因为Invoker列表已经缓存在Consumer内存中RPC调用Consumer ↓ Provider根本不经过注册中心。一张图理解ZooKeeper │ 服务注册 │ 服务发现 │ ▼ Provider1 Provider2 Provider3 \ | / \ | / \ | / ▼ ▼ ▼ Consumer 本地缓存 [ 10.1.1.10:20880, 10.1.1.11:20880, 10.1.1.12:20880 ]之后每次调用本地缓存 ↓ 负载均衡(Random/RoundRobin) ↓ 选一个Provider ↓ RPC调用面试时如果被追问注册中心在 Dubbo 调用链路中参与请求转发吗标准答案是不参与。注册中心只负责服务注册和服务发现。Consumer 获取 Provider 地址后会缓存在本地后续 RPC 调用是 Consumer 与 Provider 之间的点对点通信注册中心不会参与实际业务请求转发因此即使注册中心短暂不可用已发现的服务通常仍然可以正常调用

相关新闻