1. 需求背景
存量环境 :4 节点 Eureka 集群(A、B、E、F ,前置负载均衡 VIP),客户端心跳 5s 、租约 15s (非默认 30s),注册变化率高,配置变更需重启生效;新建 Nacos 集群(3 节点 + 外置 MySQL,鉴权开启)。
业务需求 :双注册中心并存期间,两侧微服务互相可见、Feign 调用不中断;支持同一服务的实例长期分居两侧(部分实例注册 Eureka、部分注册 Nacos,无迁移终点);终态可选迁移(下线 Eureka)或长期共存。
硬约束:Feign 调用不允许因服务发现缺失报错;任何变更步骤可回滚;注册中心运维红线(节点串行操作、负载均衡优雅摘流 + 60-90s 连接衰减、后端保持 3+ 健康节点)。
技术选型背景 (参考阿里云文章《如何平滑将注册中心从Eureka迁移到Nacos?》,按 2026 现状校正):开源 nacos-sync 已停止实质维护且基于 nacos-client 1.4.7,无法对接 Nacos 3.x (v1 API 已移除),不可用;可行路线收敛为本文两条------原文路线③(服务端同步)的内嵌形态 = 方案 A ,原文路线①(应用双注册)的正确变体 = 方案 B。
2. 整体目标
| 类别 | 目标 |
|---|---|
| 互通 | 双中心期间任一侧消费方都能发现全部服务(全量并集),Feign 零 No instances |
| 分居 | 同一服务实例分居两侧时,双侧消费方始终看到全量;实例跨侧搬迁零配置变更 |
| 平滑 | 每应用至多一次发版改造;切中心动作配置驱动、免发版;每步可回滚 |
| 收敛 | 服务变更对 Nacos 侧消费方秒级可见;对 Eureka 侧消费方 ≤90s(双层缓存固有) |
| 安全 | 注册中心故障半径可控:方案层故障不得拖垮注册节点或全量应用 |
| 终态 | 迁移型:安全下线 Eureka;共存型:双中心常驻运行 |
3. 方案 A:Eureka 内嵌 Sync 服务
同步组件直接构建进 E、F 两个 Eureka Server 节点(与 A、B 同版本同配置,A、B 保持原生),应用零改造------互通由服务端镜像复制完成。

工作原理:
- E→N:E、F 内嵌 Sync 读本地注册表 (过滤
syncSource标记)→ 镜像注册到 Nacos 并代理心跳 - N→E:订阅 Nacos 变更(秒级)→ 镜像以普通写 注册进 E/F 本地 → 经 peer 复制扩散到 A、B
- 实例下线 → 对侧镜像在同步周期内摘除;Sync 停止 → 镜像 15~30s 自动消散,不残留
核心设计(结论,推导细节见文中标注数字):
| 设计点 | 结论 |
|---|---|
| 防环 | 归属表三态(EUREKA/NACOS/BOTH,存 Nacos 配置中心,免重启)+ 镜像打 syncSource 标记、读取过滤------标记拦第二跳,配错最多各镜像一轮 |
| 镜像写入 | 必须 isReplication=false(普通写),否则镜像只留 E/F 本地、A、B 看不见,互联失效------实现最易踩的坑 |
| 写路径防重 | E、F 注册表一致,裸奔即双发。注册/摘除仅主(E)执行 (备 F 升主先全量对账);心跳主备都发 (幂等续约,且 E 故障时 F 保镜像零中断);注册通道走 v3 OpenAPI (实例按 ip:port 塌缩存储,双发塌缩成一条),禁用 SDK gRPC 连接注册(挂连接名下,双连接=列表双条目) |
| 租约与容量 | 镜像心跳 5s/次与原生对齐;心跳 QPS 按 2×镜像数/5 估算;E、F 绝不同时操作 |
| 故障语义 | E/F 同挂 → 镜像 15~30s 消散(消费方缓存再续命 ~1 分钟);镜像计入续租统计,同步双挂可能触发 Eureka 自我保护停驱逐------事件手册必备因果链 |
| 进程隔离 | gRPC 栈进老 Eureka 进程是最大工程风险:shade 隔离 + 动态 Kill Switch(不重启节点启停同步);冲突解不掉退 sidecar(同机独立 JVM) |
| 分居(BOTH) | 长期分居服务配 BOTH 双向分流,各镜像各的原生,双侧全量并集;天然兼容单侧分布(空侧空转);三道加固:标记校验对账 / 膨胀熔断(镜像 > 2×声明副本)/ 同 ip:port 双条从严 |

实施要点 :E、F 滚动升级(摘流→部署内嵌构建,同步默认关→验证→回流)→ 动态启用同步(先 E→N 单向,归属表初始全 EUREKA,试点验证)→ 分阶段:新应用上 Nacos → 老应用逐个改造(引入 nacos-discovery、移除 eureka-client,一次到位;归属翻转时机 = 该服务最后一个实例切完之后 ,早翻即事故)→ Eureka 原生归零后关同步、下线集群。回滚第一层永远是动态关同步开关(不重启节点)。
适用与代价:老应用零改造即可互通;代价是维护 Eureka fork 至下线、治理复杂(标记/归属/对账/熔断)、Sync 故障可能拖垮注册节点(靠 Kill Switch 压制)。
4. 方案 B:应用层双注册双发现 SDK
桥接做进 SDK :新应用直接采用双中心 SDK(同时注册 Eureka+Nacos、发现合并去重),老应用照旧;老应用再逐个升级同款 SDK;全员双注册后经配置翻转切 Nacos 单中心。服务端零组件、零侵入。

可行性依据 (原文路线①被否的正确变体):新应用双注册 ,Eureka 在整个共存期保持全量公共视图 ------任何时刻老应用经 Eureka 看得到所有人,双 SDK 应用合并两侧看得到所有人;没有消费方「只看 Nacos」直到最终翻转,因此结构性无环、无需任何镜像治理。
SDK 设计要点(dual-registry-starter):
| 要点 | 说明 |
|---|---|
| 组成 | eureka-client + nacos-discovery + 组合 DiscoveryClient (两侧合并,按 service+ip:port 去重,否则负载均衡双计) + 状态机 |
| 状态机 | DUAL(双注册+双发现)→ NACOS_DISCOVER(仍双注册,只从 Nacos 发现)→ NACOS_ONLY(停 Eureka 注册,下版移除 eureka-client);配置中心驱动,翻转免发版 |
| 版本适配面 | 第一可行性评估项:starter 须覆盖全部应用的 Spring Cloud 版本;老栈在 1.x 的须先升框架 |
| 翻转前置校验 | 消费方翻 NACOS_DISCOVER 前自动 diff 两侧注册中心,提供方在 Nacos 全可见才允许翻转,防实例集缩水 |
四阶段演进(每步可回滚):
| 阶段 | 动作 | 回滚 |
|---|---|---|
| 1 | 新应用上双 SDK(老应用零感知) | 改回单 Eureka 重启 |
| 2 | 老应用逐个升级双 SDK(升级 ≠ 切中心,风险低) | 换回原依赖重启 |
| 3 | 全员双注册后逐应用翻转(先翻发现观察,再停 Eureka 注册,两步降险) | 配置翻回 |
| 4 | Eureka 注册数归零(观察一个发布周期)→ 负载均衡摘流 → 下线集群 | 冷备 1~2 周 |
适用与代价 :治理最轻(原生双份,仅去重)、Eureka 零侵入、心跳天然 exactly-once;代价是每个应用一次发版 (若本就有 SDK/框架升级例行计划,代价可摊销进去)、SDK 覆盖全部 Spring Cloud 版本面、冻结应用无解。
5. 方案对比
| 维度 | 方案 A:Eureka 内嵌 Sync | 方案 B:应用层双 SDK |
|---|---|---|
| 桥接位置 | 服务端(E、F 进程内) | 应用 SDK(每个应用进程内) |
| 基础设施 | 同步 starter + E、F fork | dual-registry-starter,服务端零组件 |
| 应用改造 | 零(不升级也互通) | 每应用 1 次发版 + 配置翻转 |
| 数据模型 | 镜像 + 标记 + 归属表 + 对账 + 熔断(治理重) | 原生双份,仅合并去重(治理轻) |
| 防环 | 标记过滤 + 归属三态 + 膨胀熔断 | 结构性无环 |
| 分居支持 | BOTH 模式(三道加固) | 天然支持(双注册即常态) |
| 冻结应用 | ✅ 留 Eureka 由 Sync 桥接 | ❌ 无解 |
| 技术风险 | gRPC 进 2 个注册节点(Kill Switch 压制) | gRPC 进每个应用 + 版本适配面 |
| 故障半径 | Sync bug 可拖垮注册节点 | SDK bug 波及装载应用(分批灰度控制) |
| Eureka 侵入 | E、F 运行定制 fork 至下线 | 零侵入 |
| 收尾 | 关 Sync → 原生归零 → 下线(fork 废弃) | 配置翻转 → 注册归零 → 下线 → SDK 瘦身 |
| 回滚 | 动态关同步开关(秒级,不重启) | 配置翻回(秒级) |
6. 结论
- 主路线 = 方案 B:若存量应用本就有 SDK/框架升级例行计划,换 SDK 的发版代价可摊销进去;B 治理最轻、Eureka 零侵入、天然支持分居与无环
- 方案 A 定位兜底 :仅当存在冻结应用(无法发版/厂商锁定/禁止变更)时部署,用于桥接冻结应用;无冻结应用则 A 整体不做
- 组合形态(推荐落地):可升级应用全量走 B;冻结应用留 Eureka 由 A 桥接,最终 Eureka 缩容至仅剩冻结应用(或保留小集群 + Sync 常驻)
- 落地顺序 :
- ① 方案 B 版本适配面调研(决定性,直接决定工程量与排期;老栈在 Spring Cloud 1.x 的应用需先升框架)
- ② 盘点无法发版的冻结应用,决定是否并行建方案 A
- ③ 铺开 B:阶段 1(新应用)→ 阶段 2(老应用滚动升级,结合例行 SDK 升级计划排期)→ 阶段 3(配置翻转)→ 阶段 4(下线 Eureka)
- 两条全程红线 :Eureka 侧消费方按 90s 收敛规划发布预热(双层缓存固有);迁移期任一动作先想回滚(B 配置翻回 / A 关同步开关,均秒级)
参考 :阿里云原文《如何平滑将注册中心从Eureka迁移到Nacos?》 · nacos-sync 仓库(已不可用) · 满帮集团 MSE-Sync 案例(商业版,不适配自建)
图示约定:架构图中青色 = Eureka→Nacos 同步流,金色 = Nacos→Eureka 同步流。