7.2 Dubbo 注册中心:提供者与消费者的撮合 本节摘要:Dubbo 把服务注册、订阅发现、路由元数据三层职责交给 ZooKeeper:提供者写临时节点登记,消费者订阅名单树,配置与路由规则挂在专用目录。本判例与 5.4 节互为印证,重点看框架级实现比手写版多考虑了什么。 背景:一次调用背后的撮合 微服务调用链里,消费者发起调用前必须回答"提供者现在有谁活着"。Dubbo 把这个问题外包给注册中心,默认实现之一就是 ZooKeeper。与 5.
本节摘要:Dubbo 把服务注册、订阅发现、路由元数据三层职责交给 ZooKeeper:提供者写临时节点登记,消费者订阅名单树,配置与路由规则挂在专用目录。本判例与 5.4 节互为印证,重点看框架级实现比手写版多考虑了什么。
微服务调用链里,消费者发起调用前必须回答"提供者现在有谁活着"。Dubbo 把这个问题外包给注册中心,默认实现之一就是 ZooKeeper。与 5.4 节手写判例相比,框架版多了三样东西:接口级目录设计(一个服务接口一个目录,粒度比"一个应用一个目录"细)、双向订阅(消费者既订阅提供者名单,也把自身注册为消费者,供监控与治理)、配置路由分离(覆盖、路由等治理规则挂在独立目录,与名单数据不混放)。
Dubbo 在 ZooKeeper 上画的目录树是注册中心设计的标准答案,值得整棵记住:
/dubbo ├── com.demo.PayService # 一个接口一个目录 │ ├── providers # 提供者登记(临时节点) │ │ └── dubbo://10.0.0.1:20880?version=1.0&weight=100 │ ├── consumers # 消费者登记(临时节点,供治理) │ │ └── consumer://10.0.0.9/com.demo.PayService │ ├── routers # 路由规则(持久节点) │ │ └── condition-router:region=hangzhou │ └── configurators # 动态配置(持久节点) │ └── override://timeout=3000 └── com.demo.UserService └── ... # 同构的四个子目录
设计的三处巧思。providers 与 consumers 用临时节点:实例死则登记亡,名单永远等于活人——5.4 节的机制原样应用。routers 与 configurators 用持久节点:治理规则属于"即使没人在线也要保留"的数据,与成员数据期限不同。节点名即数据:提供者的 URL 连同版本、权重直接编进节点名,读名单不必逐个 getData——一次 getChildren 拿全名单,把 4.3 节"事件不带数据"的短板绕开了。这是比手写版高明的一处:把数据塞进名字,读模型就只需一层。
消费者端的订阅流程与 3.2 节的读-听循环同源,但框架版在两个位置做了加固。其一,全量重推:名单变化时 Dubbo 重新拉全目录,不做增量拼装(与 5.4 节的"全量重建"决策一致,理由同样:事件乱序下的增量拼装会错漏名单)。其二,空名单保护:收到"提供者清空"的通知时,框架不会立刻把本地名单清空,而是保留旧名单继续服务并打告警——因为一次注册中心的抖动不该导致所有调用全部失败,这是把"通知非强实时"(4.3 节边界)翻译成业务可用性的典型手法。
# 用 zkCli 亲眼查看一次 Dubbo 的注册现场(连到注册中心集群) [zk] ls /dubbo/com.demo.PayService/providers [dubbo://10.0.0.1:20880/com.demo.PayService?anyhost=true&application=pay-app &dubbo=2.0.2&interface=com.demo.PayService&methods=query,pay&pid=12345 &side=provider×tamp=1724990000000] # 治理规则现场:给接口下发超时覆盖 [zk] create /dubbo/com.demo.PayService/configurators "override://timeout=3000" # 消费者几秒内收到 configurators 子节点变化通知,调用超时按 3000 毫秒生效 # —— 5.1 节配置中心判例在框架内的直接复用
框架级实现也带来新的问题清单。写放大:Dubbo 的接口级注册意味着一个应用可能注册几十个接口目录,每个目录下每个实例一个节点,加上消费者登记,大集群的 ZNode 数量轻松过十万——4.1 节的写路径与 6.4 节的快照都在替这份规模买单。Dubbo 后来的改进方向也由此而来:应用级注册(只按应用名注册一份,接口到实例的映射由消费者本地解析),注册数据量下降一个数量级,代价是消费者要做本地服务发现解析。这是"框架权衡注册粒度"的现成案例:粒度越细治理越方便,数据量越大协调层越重。
多注册中心与元数据中心:Dubbo 支持同时向多个注册中心注册(迁移期双写)、并把"接口定义这类大块元数据"拆到独立的元数据中心存储——后者本质上是承认 1.2 节的边界:注册中心只存路由必需的小数据,定义类数据另有去处。
把 Dubbo 的设计收进你的工具箱,四条即可:目录按"服务粒度"规划并预留治理子目录;成员数据用临时、规则数据用持久;把路由必需的数据编进节点名减少读放大;名单消费加空名单保护与全量重建。这四条加上 5.4 节的机制原理,足以支撑你自研一套贴合业务的注册中心。
问:Dubbo 还能不换注册中心改用 Nacos 吗? 可以,配置即可切换。Nacos 把注册与配置合在一套服务里且支持 AP 模式,云原生语境更流行;但只要理解本章的目录设计与通知机制,迁移只是换个实现,知识完全平移。
最后一站:把 ZooKeeper 与它的替代品放上同一张台子,回答"新项目该怎么选"。