GitHub user AlexStocks edited a discussion: nacos-go-sdk 从 v2 升级到 v3

# apache/dubbo-go Nacos v2 to v3 升级方案

## 1. 背景

`dubbo-go-samples` 中的 Nacos v3 验证不应作为升级起点。Sample 只能证明某个示例链路是否跑通,无法定义 
`apache/dubbo-go` 对 Nacos 3.x 的真实兼容边界。本次升级应从 `apache/dubbo-go` 主仓开始,先完成框架层的 
Nacos 3.x 兼容性确认、必要改造和自动化验证,再使用 `dubbo-go-samples` 作为集成验收入口。

当前 `apache/dubbo-go` 已经依赖 `github.com/nacos-group/nacos-sdk-go/v2 v2.2.5`,并且已有 
Nacos 注册中心、配置中心和元数据中心实现。升级的重点不是新增 Nacos 支持,而是确认现有实现能否在 Nacos 3.x 
下稳定工作,并补齐鉴权、命名空间、数据库迁移、生命周期和回滚策略。

## 2. 升级目标

本次升级目标如下:

- 确认 `apache/dubbo-go` 对 Nacos 3.x 的支持范围和限制。
- 保证注册中心、配置中心、元数据中心三条 Nacos 链路在 Nacos 3.x 下行为可验证。
- 明确鉴权开启和关闭两种模式下的客户端配置方式。
- 明确 Nacos 服务端数据库 schema 变更和回滚策略。
- 建立可复现的自动化测试、集成测试和 samples 验收流程。
- 形成一条可以灰度发布、可以回滚、可以定位失败原因的升级路径。

本方案不以“只跑通 `dubbo-go-samples/registry`”为成功标准。最终成功标准必须落在 `apache/dubbo-go` 主仓能力上。

## 3. 当前主仓基线

### 3.1 依赖基线

主仓当前使用:

```text
github.com/nacos-group/nacos-sdk-go/v2 v2.2.5
```

这说明当前代码已经处于 Nacos Go SDK v2 客户端体系内。根据 Nacos 官方升级文档,Nacos 3.x server 与 2.x 
client 兼容,因此第一阶段不应默认升级 SDK,而应先验证当前 SDK 在 dubbo-go 现有封装下的实际表现。

参考:

- https://nacos.io/en/docs/latest/manual/admin/upgrading/
- https://github.com/apache/dubbo-go/blob/main/go.mod

### 3.2 dubbo-go 中的 Nacos 入口

主仓至少存在三类 Nacos 能力入口:

- 注册中心:`registry/nacos`
- 配置中心:`config_center/nacos`
- 元数据中心:`metadata/report/nacos`

底层客户端构造逻辑集中在:

- `remoting/nacos/builder.go`

该文件负责从 `common.URL` 中解析 Nacos 
服务地址、namespace、用户名、密码、AK/SK、timeout、endpoint、cache、log 等客户端配置。因此,本次升级需要重点验证 
`common.URL -> nacos ClientConfig/ServerConfig -> SDK client` 的参数映射是否完整、明确、可诊断。

## 4. 升级原则

### 4.1 主仓优先

升级顺序必须是:

1. `apache/dubbo-go` 主仓完成兼容性确认和必要改造。
2. 主仓测试和集成环境验证通过。
3. `dubbo-go-samples` 更新配置和运行手册。
4. 使用 samples 作为最终验收和用户文档验证。

不能先在 samples 中绕过主仓问题,否则容易出现示例跑通但真实用户场景失败的情况。

### 4.2 不默认升级 SDK

第一阶段先基于当前 `nacos-sdk-go/v2 v2.2.5` 验证 Nacos 3.x。只有出现明确的 SDK 缺陷或官方文档要求时,才升级 SDK。

SDK 升级需要单独评审:

- 是否引入破坏性 API 变化。
- 是否改变默认超时、缓存、日志、鉴权行为。
- 是否影响现有 Nacos 2.x 用户。
- 是否需要同步更新 mock、单测和文档。

### 4.3 鉴权分层处理

Nacos 3.x 的鉴权必须拆成两条线:

- 控制台鉴权。
- 客户端访问鉴权。

官方文档中 `nacos.core.auth.enabled` 默认值为 
`false`,用于客户端访问鉴权;`nacos.core.auth.console.enabled` 默认值为 `true`,用于控制台访问鉴权。Nacos 
3.0 起控制台访问默认开启鉴权,但这不等价于客户端注册发现默认必须带用户名密码。

因此,升级方案中不能简单写“v3 默认开启鉴权,所以客户端必须配置用户名密码”。正确表达应为:

- 如果只开启控制台鉴权,dubbo-go 客户端注册发现不一定需要用户名密码。
- 如果开启 `nacos.core.auth.enabled=true`,dubbo-go 客户端必须正确传递用户名密码或其他认证参数。
- 鉴权失败必须在启动或注册阶段有明确日志和错误信息。

参考:

- https://nacos.io/docs/v3.0/manual/admin/auth/

### 4.4 数据库不可被当成透明实现细节

Nacos 3.2.x 支持从 2.0.x ~ 3.1.x 升级,但官方文档明确说明数据库 schema 有变化,升级前需要对比并应用新的 
`mysql-schema.sql`。Nacos 3.2.0 还新增 AI 相关表。

因此,回滚策略不能只写“切回 Nacos v2”。如果 v2 和 v3 共用同一数据库,schema 
变化可能已经影响回滚边界。首次验证必须优先使用独立数据库或由备份恢复出的数据库副本。

## 5. 影响范围

### 5.1 注册中心

注册中心需要覆盖:

- Provider 注册。
- Provider 反注册。
- Consumer 订阅。
- Consumer 取消订阅。
- 全量服务查询。
- 实例列表变化监听。
- Nacos 重启后的恢复。
- 网络抖动后的恢复。
- 鉴权失败时的错误暴露。

重点代码区域:

- `registry/nacos/registry.go`
- `registry/nacos/listener.go`
- `remoting/nacos/builder.go`

重点风险:

- `RegisterInstance` 返回 `false` 但 error 为空时是否有明确错误。
- `Subscribe` 失败后的重试是否会退出过早或无限泄露 goroutine。
- `Destroy` 中关闭监听器、反注册、关闭 client 的顺序是否稳定。
- `IsAvailable` 使用 `GetAllServicesInfo` 探活时,在 Nacos 3.x 鉴权失败或异常返回下是否会误判。

### 5.2 配置中心

配置中心需要覆盖:

- 读取配置。
- 发布配置。
- 删除配置。
- 监听配置变更。
- 取消监听。
- 按 group 查询配置 key。
- 空 namespace 与 `public` namespace 的兼容。

重点代码区域:

- `config_center/nacos/impl.go`
- `config_center/nacos/client.go`
- `config_center/nacos/facade.go`
- `remoting/nacos/builder.go`

重点风险:

- Nacos 3.0 对 config namespace 做了迁移和兼容处理,`namespaceId=""` 与 
`namespaceId="public"` 的行为需要显式验证。
- `Destroy` 直接关闭 `done`,需要确认重复调用或异常初始化失败时不会 panic。
- 配置不存在错误不能被误判为连接失败。

### 5.3 元数据中心

元数据中心需要覆盖:

- 应用元数据发布。
- 应用元数据读取。
- 服务到应用映射发布。
- 服务到应用映射读取。
- 映射监听。
- 映射取消监听。

重点代码区域:

- `metadata/report/nacos/report.go`
- `remoting/nacos/builder.go`

重点风险:

- 元数据中心复用 Nacos config client,容易被配置中心 namespace 迁移影响。
- 当前实现兼容 Java 元数据格式和 dubbo-go 旧格式,升级测试必须同时覆盖两种 dataId/group 组合。
- `CreateMetadataReport` 返回 `nil` 时上层是否能明确处理。

## 6. 目标版本与环境矩阵

### 6.1 Nacos 服务端版本

建议至少准备以下环境:

| 环境 | Nacos 版本 | 用途 |
| --- | --- | --- |
| 基线环境 | 当前生产或样例使用的 Nacos 2.x | 对照组 |
| 目标环境 | Nacos 3.2.x | 本次主要升级目标 |
| 兼容环境 | Nacos 3.0.x 或 3.1.x | 如需声明泛 3.x 支持时使用 |

如果只计划支持 Nacos 3.2.x,不要在文档中承诺“支持所有 3.x”。可以写成“本次以 Nacos 3.2.x 为验收目标,其他 3.x 
小版本仅做兼容参考”。

### 6.2 鉴权矩阵

必须验证两种模式:

| 模式 | 服务端配置 | 客户端期望 |
| --- | --- | --- |
| 客户端鉴权关闭 | `nacos.core.auth.enabled=false` | 不配置用户名密码也能注册、发现、读写配置 |
| 客户端鉴权开启 | `nacos.core.auth.enabled=true` | 必须配置用户名密码,认证失败要有明确错误 |

控制台鉴权单独验证,不作为客户端兼容结论。

### 6.3 数据库矩阵

首次升级验证建议使用:

| 数据库 | 策略 |
| --- | --- |
| v2 基线库 | 保持不变,只读对照 |
| v3 验证库 | 从 v2 备份恢复后执行 schema 升级 |
| 回滚验证库 | 从升级前备份恢复,验证回滚步骤 |

禁止在没有备份和回滚演练的情况下让 v3 首次验证直接连接生产 v2 数据库。

## 7. 实施阶段

### 7.1 阶段一:事实盘点

输出一份影响清单,包含:

- 当前 dubbo-go 依赖的 `nacos-sdk-go` 版本。
- 所有 Nacos 相关 package。
- 所有 Nacos 配置项。
- 注册中心、配置中心、元数据中心是否都在目标业务中启用。
- samples 中实际依赖 Nacos 的 demo 清单。

建议命令:

```bash
go list -m github.com/nacos-group/nacos-sdk-go/v2
grep -R "nacos" -n registry config_center metadata remoting config common
```

Windows 环境可使用 PowerShell:

```powershell
Get-ChildItem -Recurse -File | Select-String -Pattern "nacos"
```

阶段退出标准:

- 影响范围明确。
- 不存在“只知道 registry,遗漏 config center 或 metadata report”的情况。

### 7.2 阶段二:本地兼容性验证

启动两套 Nacos:

- Nacos 2.x:基线。
- Nacos 3.2.x:目标。

每套环境都跑同一批 dubbo-go 测试和最小集成链路。

验证内容:

- 当前 `nacos-sdk-go/v2 v2.2.5` 是否能连接 Nacos 3.2.x。
- `remoting/nacos/builder.go` 生成的 `ServerConfig` 和 `ClientConfig` 是否正确。
- 地址、context path、namespace、group、username、password、timeout 是否按预期传入 SDK。

阶段退出标准:

- Nacos 3.2.x 下注册中心最小链路可运行。
- 鉴权关闭和开启模式各有明确结论。
- 如果失败,能定位到服务端配置、dubbo-go 参数映射、SDK 行为或样例配置中的某一类。

### 7.3 阶段三:主仓改造

根据阶段二结果决定是否需要改代码。

优先改造项:

- 补齐 Nacos 3.x 鉴权配置文档和示例。
- 增强 Nacos client 初始化错误信息,避免把认证失败、地址错误、namespace 错误全部包装成模糊错误。
- 补充 `remoting/nacos/builder.go` 的单元测试,覆盖 Nacos 3.x 关键参数。
- 补充 registry/config center/metadata report 在鉴权失败、连接失败、配置不存在下的错误路径测试。
- 如发现生命周期问题,修复 `Destroy`、listener、retry、client close 顺序。

SDK 升级不是默认动作。只有满足以下条件之一时才升级:

- Nacos 3.x 目标功能要求新版 SDK。
- 当前 SDK 在 Nacos 3.x 下存在已确认缺陷。
- 官方文档或 issue 明确建议升级。
- 新版 SDK 修复了本次升级阻塞问题,且对 Nacos 2.x 用户无破坏性影响。

阶段退出标准:

- 主仓单测通过。
- Nacos 相关新增测试覆盖关键分支。
- 不引入对 Nacos 2.x 的兼容性回退。

### 7.4 阶段四:集成测试

集成测试需要覆盖三条链路。

注册中心:

- Provider 启动并注册成功。
- Consumer 发现 provider。
- RPC 调用成功。
- Provider 停止后 Nacos 实例下线。
- Provider 重启后 Consumer 能恢复调用。
- Nacos 重启后实例和订阅最终恢复。

配置中心:

- 发布配置成功。
- 读取配置成功。
- 监听配置变更成功。
- 删除配置后读取行为符合预期。
- `namespaceId=""` 和 `namespaceId="public"` 场景有明确结论。

元数据中心:

- 应用元数据发布成功。
- 应用元数据读取成功。
- 服务应用映射发布成功。
- 映射监听能收到变更。
- Java 兼容格式和 dubbo-go 旧格式都能覆盖。

阶段退出标准:

- 三条链路在 Nacos 3.2.x 下全部通过。
- 失败路径有日志,有错误,有归因。

### 7.5 阶段五:samples 验收

主仓通过后,才进入 samples。

samples 的职责:

- 验证用户可理解的配置方式。
- 验证 README 和命令是否可复现。
- 验证 registry、config center、metadata 场景是否能作为用户示例。

samples 不负责定义主仓兼容策略。

需要输出:

- Nacos 2.x 运行结果。
- Nacos 3.2.x 运行结果。
- 鉴权关闭运行结果。
- 鉴权开启运行结果。
- 失败样例和原因列表。

阶段退出标准:

- samples 文档能指导用户启动 Nacos 3.x。
- 用户不需要读主仓源码即可配置用户名、密码、namespace、group。
- 失败场景有明确排查入口。

## 8. 数据库升级方案

### 8.1 首次验证

首次验证不得直接改生产或共享 v2 数据库。

推荐步骤:

1. 备份 v2 Nacos 数据库。
2. 恢复到独立 v3 验证库。
3. 对比当前版本和目标版本的 `mysql-schema.sql`。
4. 执行 Nacos 官方要求的 schema 变更。
5. 启动 Nacos 3.2.x。
6. 查看 `logs/startup.log` 和 `logs/nacos.log`。
7. 通过 dubbo-go 注册、配置、元数据链路验证数据可用。

### 8.2 回滚边界

如果 v3 使用独立数据库,回滚方式是切回 v2 Nacos 地址和 v2 数据库。

如果 v2 和 v3 共用数据库,回滚必须满足:

- 升级前有完整数据库备份。
- 已演练从备份恢复到 v2。
- 明确 schema 变更是否可逆。
- 明确 v3 运行期间写入的新数据是否需要迁回 v2。

不能在共库方案里承诺“配置切换即可回滚”。

### 8.3 Config Namespace 迁移

Nacos 3.0 将配置中心的空 namespace 与 `public` namespace 做了统一和兼容处理。官方文档说明,兼容模式默认开启,可通过 
`nacos.config.namespace.compatible.mode` 关闭;关闭后将不再具备平滑降级能力。

因此:

- 升级初期保持兼容模式开启。
- 验证配置中心读写和监听后,再评估是否关闭兼容模式。
- 关闭兼容模式前必须确认不再需要平滑回退到旧行为。
- 如果日志中出现 namespace 迁移冲突,需要先清理冲突配置,再继续验证。

## 9. 鉴权升级方案

### 9.1 服务端配置

如果开启客户端鉴权,Nacos 服务端至少需要配置:

```properties
nacos.core.auth.system.type=nacos
nacos.core.auth.enabled=true
nacos.core.auth.admin.enabled=true
nacos.core.auth.console.enabled=true
nacos.core.auth.plugin.nacos.token.secret.key=${custom_base64_token_secret_key}
nacos.core.auth.server.identity.key=${custom_server_identity_key}
nacos.core.auth.server.identity.value=${custom_server_identity_value}
```

Docker 环境至少需要:

```bash
NACOS_AUTH_ENABLE=true
NACOS_AUTH_TOKEN=${custom_base64_token_secret_key}
NACOS_AUTH_IDENTITY_KEY=${custom_server_identity_key}
NACOS_AUTH_IDENTITY_VALUE=${custom_server_identity_value}
```

### 9.2 dubbo-go 客户端配置

dubbo-go 侧应通过现有配置字段传递认证信息:

```yaml
dubbo:
  registries:
    nacos:
      protocol: nacos
      address: 127.0.0.1:8848
      username: nacos
      password: ${NACOS_PASSWORD}
      namespace: public
      group: DEFAULT_GROUP
```

配置中心和元数据中心也需要分别验证用户名、密码、namespace、group 是否正确透传。不能只验证 registry。

### 9.3 失败行为

必须覆盖以下失败场景:

- 未配置用户名密码但服务端开启客户端鉴权。
- 用户名错误。
- 密码错误。
- namespace 不存在。
- group 配置错误。
- token secret 或 server identity 配置不一致。

验收要求:

- 错误不能被吞掉。
- 日志必须能区分认证失败和网络失败。
- Provider 不应在注册失败后表现为“启动成功但不可发现”。

## 10. 测试方案

### 10.1 单元测试

建议补充或确认以下测试:

- `remoting/nacos/builder.go`:URL 到 Nacos config 的映射。
- `registry/nacos`:注册、反注册、订阅、取消订阅参数构造。
- `config_center/nacos`:配置不存在、发布失败、删除失败、监听失败。
- `metadata/report/nacos`:metadata dataId/group 兼容格式。

### 10.2 集成测试

建议通过 Docker Compose 或 CI service 启动 Nacos 2.x 和 3.2.x。

测试矩阵:

| 链路 | Nacos 2.x | Nacos 3.2.x 鉴权关 | Nacos 3.2.x 鉴权开 |
| --- | --- | --- | --- |
| Registry register/unregister | 必测 | 必测 | 必测 |
| Registry subscribe/unsubscribe | 必测 | 必测 | 必测 |
| RPC provider/consumer | 必测 | 必测 | 必测 |
| Config get/publish/delete/listen | 如当前支持 | 必测 | 必测 |
| Metadata publish/read/listen | 如当前支持 | 必测 | 必测 |

### 10.3 稳定性测试

稳定性测试至少包含:

- 长稳运行 24 小时。
- Provider 每 30 秒重启一次,持续 30 分钟。
- Nacos 单节点重启。
- Nacos 全集群滚动重启。
- Consumer 持续调用,观察错误率和恢复时间。
- 注册实例数量放大到至少 100 个。
- 订阅服务数量放大到至少 100 个。

### 10.4 资源泄露测试

重点观察:

- goroutine 数量。
- Nacos SDK client 数量。
- listener cache 大小。
- 连接数。
- 日志错误频率。
- 进程内存。

特别关注订阅失败重试、Nacos 重启、Consumer 销毁、配置监听取消这些路径。

## 11. 发布方案

### 11.1 发布阶段

建议按以下顺序推进:

1. 本地验证:开发者本地运行 Nacos 3.2.x。
2. CI 验证:新增 Nacos 3.2.x 集成测试。
3. 测试环境:业务应用连接 Nacos 3.2.x 验证。
4. 预发环境:开启与生产一致的鉴权、namespace、group、数据库配置。
5. 生产灰度:少量 Provider 和 Consumer 切到 Nacos 3.2.x。
6. 全量切换:观察稳定后全量切换。

### 11.2 灰度策略

优先采用双环境灰度:

- Nacos 2.x 保持原链路。
- Nacos 3.2.x 使用独立地址和数据库。
- dubbo-go 应用通过配置切换 registry/config/metadata 地址。

如果业务允许,可评估双注册:

- Provider 同时注册到 v2 和 v3。
- Consumer 分批切到 v3。
- 灰度期间对比 v2/v3 实例数、健康状态和调用成功率。

双注册需要单独评审,不应默认纳入第一阶段。

### 11.3 观测指标

发布期间必须观察:

- 注册成功率。
- 反注册成功率。
- 订阅成功率。
- RPC 成功率。
- RPC P99 延迟。
- Consumer 实例列表为空次数。
- Provider 频繁上下线次数。
- Nacos 登录或鉴权失败次数。
- Nacos server CPU、内存、连接数、数据库 QPS。
- dubbo-go 进程 goroutine、内存、日志错误数。

## 12. 回滚方案

### 12.1 可快速回滚的前提

只有满足以下条件时,才能承诺快速回滚:

- v2 Nacos 环境保持运行。
- v2 数据库未被 v3 schema 或 v3 写入破坏。
- 应用配置可以快速切回 v2 地址。
- 没有关闭 Nacos 3.x config namespace 兼容模式。
- 业务没有只写入 v3 而未同步回 v2 的关键配置或元数据。

### 12.2 回滚步骤

推荐步骤:

1. 停止继续扩大 v3 灰度。
2. 将 Consumer 配置切回 v2 Nacos。
3. 将 Provider 配置切回 v2 Nacos。
4. 确认 Provider 在 v2 控制台可见。
5. 确认 Consumer 能发现实例。
6. 确认 RPC 调用恢复。
7. 保留 v3 环境现场日志和数据库,不立即清理。
8. 汇总失败原因后再决定是否重试升级。

### 12.3 不可快速回滚场景

以下情况不能写作快速回滚:

- v2 和 v3 共用数据库且无恢复演练。
- 关闭了 namespace 兼容模式。
- 业务配置只在 v3 修改,v2 不具备同等数据。
- 应用代码已经依赖只在 Nacos 3.x 存在的行为。

## 13. 验收标准

本次升级完成必须满足:

- `apache/dubbo-go` 主仓明确声明支持的 Nacos 3.x 版本。
- registry、config center、metadata report 三条链路均有验证结论。
- 鉴权开启和关闭两种模式均有测试结果。
- 数据库升级和回滚策略可执行。
- Nacos 2.x 回归通过,不破坏存量用户。
- `dubbo-go-samples` 能作为用户示例跑通 Nacos 3.x。
- 文档中说明 username、password、namespace、group、auth 开关和数据库 schema 注意事项。
- 所有 P0/P1 问题关闭后才能进入生产灰度。

## 14. 待办清单

### P0

- 确认目标 Nacos 3.x 小版本,禁止泛化承诺所有 3.x。
- 使用独立数据库完成 v3 schema 升级验证。
- 验证 registry/config center/metadata report 三条链路。
- 验证客户端鉴权开启时 username/password 透传。
- 验证回滚流程,不能只写配置切回。

### P1

- 补充 `remoting/nacos/builder.go` 参数映射测试。
- 补充 Nacos 鉴权失败、namespace 错误、连接失败的错误路径测试。
- 补充 samples 的 Nacos 3.x 配置示例。
- 补充 Nacos 3.x 运行手册,包括 Docker 环境变量和管理员密码初始化。
- 补充长稳和资源泄露测试记录。

## 15. 最终结论

Nacos v2 到 v3 的升级应从 `apache/dubbo-go` 主仓开始,而不是从 `dubbo-go-samples` 开始。主仓需要先证明自身 
Nacos 适配层在 Nacos 3.x 下的行为稳定、可诊断、可回滚,再让 samples 作为用户侧验收。

本次升级的核心风险不在“能不能连接 Nacos 3.x”,而在:

- 鉴权是否被正确理解和配置。
- 数据库 schema 变更是否破坏回滚边界。
- config namespace 迁移是否影响配置中心和元数据中心。
- 注册、订阅、监听、销毁生命周期是否在异常场景下稳定。
- Nacos 2.x 存量用户是否被兼容性改造影响。

只有这些风险都有明确结论后,才能认为 dubbo-go 对 Nacos 3.x 的升级方案完成。


GitHub link: https://github.com/apache/dubbo-go/discussions/3318

----
This is an automatically sent email for [email protected].
To unsubscribe, please send an email to: 
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to