Nacos 3.x 兼容与废弃治理机制:六态兼容模型、410 Gone 废弃 API 门控与 Legacy 迁移路径
【免费下载链接】nacosan easy-to-use dynamic service discovery, configuration and service management platform for building AI cloud native applications.项目地址: https://gitcode.com/GitHub_Trending/na/nacos
本文围绕 Nacos 仓库中的设计规格specs/en/design/compatibility-deprecation-spec.md展开,系统讲解 Nacos 对 API、SDK、存储字段、插件与实验性能力所采用的统一兼容与废弃治理规则。读完后你将能够:准确判断任意 Nacos 历史行为属于哪种兼容状态、知道被废弃端点返回 HTTP410 Gone的底层实现与重开开关nacos.core.api.compatibility.enabled的适用边界,并掌握 v1/v2 Legacy HTTP API 适配器、Legacy MCPmcpId与 A2A AgentCard 门面等当前已知兼容项的迁移路径与移除条件。
1. 规格定位与治理边界
Nacos 的 兼容与废弃规格 定义了跨模块共享的治理规则,覆盖 API、SDK、存储字段、插件扩展点与实验性能力。它与 Nacos 设计规格、资源模型规格 以及各公开接口规格互为补充,是整个specs/体系中的“规则层”文档。
该规格明确拥有以下四类决策权:
- 历史行为如何被分类为canonical(规范行为)、compatibility-only(仅兼容)、deprecated(已废弃)、pending removal(待移除)、experimental(实验性)或removed(已移除);
- 废弃或仅兼容行为的文档要求;
- API、SDK 接口、存储字段、插件扩展点的迁移预期;
- 能力门控(ability-gated)回退的移除规则。
值得强调的是,该规格不设定固定的发布日历:每一次具体的废弃行为仍需对应领域的维护者评审,并通过 Release Note 向用户传达。这避免了“按版本号一刀切”的治理僵化,把节奏判断留给各领域维护者。
2. 六态兼容模型:判断历史行为“该不该用”的标尺
规格第 2 节给出了 Nacos 兼容治理的核心状态机。任何历史行为(一个端点、一个 SDK 方法、一个数据库字段、一个插件配置键)都必须落入以下六种状态之一:
| 状态 | 含义 | 新开发规则 |
|---|---|---|
| Canonical(规范) | 由规格定义、面向新使用场景的当前行为 | 新代码与文档都应使用它 |
| Compatibility-only(仅兼容) | 为避免破坏现有用户而保留,但不是目标模型 | 除缺陷修复与迁移支持外不得扩展 |
| Deprecated(已废弃) | 仍可用,但用户应迁移到替代方案 | 必须记录替代方案与迁移指引 |
| Pending removal(待移除) | 移除条件已明确的废弃行为 | 只保留必要的兼容性测试与迁移指引 |
| Experimental(实验性) | 尚未承诺为稳定行为 | 允许在不兼容变更或删除时给出明确说明 |
| Removed(已移除) | 当前版本不再支持 | 规格仅在必要时描述迁移历史 |
两条附加规则容易被忽视但很关键:
- 新规格必须显式标注“非规范”行为——某个行为即使存在于代码、数据库结构、配置或历史文档中,也不足以让它获得 canonical 地位。换句话说,“代码里存在”不等于“应该继续使用”,规格才是唯一授权来源。
- 这条原则正是第 9 节废弃 V3 API 门控的哲学基础:与其让废弃端点无限期存活,不如用明确的门禁让它“可见地失效”。
3. 文档规则:废弃行为不得“静默消失”
规格第 3 节规定了文档层面的硬性要求:只要实现仍在支持,废弃或仅兼容的行为就不允许从文档中静默删除。它必须出现在专门的兼容性或废弃章节中,且该章节必须包含五个要素:
- 当前状态(Deprecated / Compatibility-only / Pending removal 等);
- 替代物:替代 API、字段、SDK 方法或插件模型;
- 迁移指引;
- 兼容性风险:包括认证(auth)、可见性(visibility)或响应结构(response-shape)上的差异;
- 移除条件(若已知)。
同时要求面向用户的主流程文档优先描述 canonical 行为,兼容章节必须处于明显的次要位置。这一条直接约束了 Nacos 各 HTTP API 文档的写法:例如在 V3 API Surface 规格 中,废弃端点被统一收纳在兼容小节而非与规范端点并列。
4. API 与 SDK 规则:兼容强度分层
规格第 4 节对不同接口的“长期兼容预期”做了分层:
- Open API(开放 API)承担最强的长期兼容预期;
- Admin、Console、Maintainer SDK 以及插件提供的 API 演进可以更快,但一旦发生不兼容变更且用户可能依赖了已文档化的行为,仍必须提供迁移指引;
- 废弃端点应收留在兼容章节,而不是继续当作主 API 呈现;新的 API 定义不允许“因为旧形状已经存在”就照抄 legacy 结构;
- SDK 在合理范围内应对废弃的公开方法保持二进制兼容,尤其是 Java 的 client、api、plugin 模块;新 SDK 特性应把用户引向 canonical 接口,不应扩展已废弃的写接口或宽泛查询面。
这一分层解释了仓库中不同模块的差异:client/、maintainer-client/等 Java 模块对公共方法签名变化保持克制,而console/内部的 Console API 可以在版本间快速迭代(如第 9 节中 3.2.1 即废弃一批 Pipeline 路径参数式端点)。
5. Ability-Gated Fallback:混版本集群中的回退纪律
Nacos 集群滚动升级时常出现新旧版本节点共存。规格第 5 节确立了原则:能力协商(ability negotiation)是首选的混版本机制,客户端/服务端通过能力位声明自身支持范围,而不是靠服务端猜测。回退(fallback)只有在所属领域规格明确记录以下四项信息后才被允许:
- 门控 canonical 行为的能力键(ability key)或条件;
- 精确的 fallback 行为;
- fallback 是否改变响应结构、一致性、安全性或性能;
- fallback何时可以移除。
移除时机同样被约束:必须等到最小受支持的 server/client 版本矩阵不再需要该回退,或者社区明确接受该不兼容变更,才允许移除。这套规则与 客户端能力协商规格 配套,是 Nacos 滚动升级平滑性的制度保障。
6. 存储与 Schema 规则:兼容字段不得“借尸还魂”
规格第 6 节针对数据库与持久层:
- 仅为兼容而保留的存储字段必须被文档标注为 compatibility field 或 pending-removal field;除非后续领域规格显式提升它,否则它不得获得新的领域语义。
- Schema 清理需要在正确性与运维成本之间平衡:一个冗余字段可以暂时保留以避免用户频繁做 schema 变更,但新的规格、API、SDK 与文档不得在这个字段之上构建新行为。
第 8 节给出了这条规则的真实案例:在 Nacos 3.3 线中,Config 默认命名空间的存储迁移(从 legacy 空 tenant 值到public),以及 Config beta/tag 旧表迁移到config_info_gray表,都被视为已移除(removed)的兼容行为。这意味着:从 3.0 之前版本升级的操作者,若曾使用默认命名空间或 beta 灰度发布,必须在升级前完成受影响的数据迁移。这是一条有实际运维后果的规则,而非纸面约定。
7. 插件与适配器:兼容别名的边界
规格第 7 节对两类“外围兼容面”分别立规:
插件 SPI:SPI 的兼容性归属其所属插件规格(见 插件规格总览)。插件可以保留历史配置键或扩展名作为兼容别名(compatibility aliases),但规范的插件查找与启用方式必须单独文档化——别名不能替代规范路径成为文档主角。
适配器(Adapter):对外暴露社区协议的适配器属于兼容面,而非 canonical 的 Nacos API 模型。它们可以有意跟随外部协议的结构或路由约定,但必须被文档标注为 adapter 行为;如果引入了未认证端点或额外端口,应当是 opt-in 的。第 10 节的 v1/v2 Legacy HTTP API 适配器正是按这条规则运作的典型代表。
8. 当前已知兼容项清单
规格第 8 节列出了当前仓库中的兼容/废弃示例(非穷尽清单,各领域的精确行为与迁移细节仍由对应领域规格负责):
- v1/v2 HTTP API:已移出主 server 发行版,迁移至独立的
nacos-api-legacy-adapter项目(见第 10 节); - pre-spec v3 兼容端点;
- AI Prompt legacy 端点与legacy Pipeline REST 风格端点;
- legacy MCP Console 导入端点:默认禁用,在迁移到统一 AI 资源导入端点后,计划在Nacos 3.4.0移除;
- legacy MCP
mcpId输入/输出:作为兼容别名保留,规范管理已转为 Namespace 作用域的mcpName; - legacy A2A AgentCard 门面:覆盖 Java、gRPC、Admin、Maintainer 与 Console 各层;
- Naming API 定义的 service selector 字段与请求参数;
- Config 聚合字段及相关数据库列;
- 历史插件配置键;
- 仍位于历史路径下的 OIDC 浏览器端点;
- Distributed Lock(分布式锁):在提升为 stable 之前属于实验性能力(对应 lock 规格)。
这份清单的价值在于:它为“某段旧代码/旧接口还能活多久”提供了唯一权威的索引。结合第 6 节所述的 3.3 线 Config 迁移案例,运维者在制定升级计划时应以该清单逐项核对自身使用面。
9. Deprecated V3 API 门控:默认关闭的废弃端点与 410 Gone
这是本规格中最具工程落地感的一节。仓库中存在一小批“待移除的废弃 v3 API”,它们默认被禁用,并接入统一的兼容门控:
| 废弃 API | 规范替代 |
|---|---|
GET /v3/admin/ai/pipelines | GET /v3/admin/ai/pipelines/list |
GET /v3/admin/ai/pipelines/{pipelineId} | GET /v3/admin/ai/pipelines/detail?pipelineId={pipelineId} |
GET /v3/console/ai/pipelines | GET /v3/console/ai/pipelines/list |
GET /v3/console/ai/pipelines/{pipelineId} | GET /v3/console/ai/pipelines/detail?pipelineId={pipelineId} |
POST /v3/console/ai/mcp/import/validate | POST /v3/console/ai/import/validate |
POST /v3/console/ai/mcp/import/execute | POST /v3/console/ai/import/execute |
9.1 门控实现:从CompatibilityHelper到 410 Gone
被禁用的端点返回HTTP410 Gone,结果码为API_DEPRECATED,并在响应体中指明其规范替代端点。其核心实现只有 55 行,位于 CompatibilityHelper.java:
public final class CompatibilityHelper { public static final String API_COMPATIBILITY_ENABLED_KEY = "nacos.core.api.compatibility.enabled"; private static final String DEPRECATED_API_MESSAGE = "Current API is deprecated. Please use API(s) `%s` instead, or set `%s=true` " + "in application.properties during migration."; /** * Check whether deprecated API compatibility is enabled. */ public static void check(String alternatives) throws NacosApiException { if (EnvUtil.getProperty(API_COMPATIBILITY_ENABLED_KEY, Boolean.class, false)) { return; } throw new NacosApiException(HttpStatus.GONE.value(), ErrorCode.API_DEPRECATED, String.format(DEPRECATED_API_MESSAGE, alternatives, API_COMPATIBILITY_ENABLED_KEY)); } }三个实现要点与规格逐条对应:
- 默认关闭:
EnvUtil.getProperty(..., Boolean.class, false)的默认值为false,即开关缺省状态下废弃端点直接抛异常——与“默认禁用”的规格要求一致; 410 Gone+API_DEPRECATED:HttpStatus.GONE.value()即 410;ErrorCode.API_DEPRECATED定义于 ErrorCode.java(错误码40000, "API deprecated.",位于api模块的 v2 模型包中,可被所有 HTTP 响应层复用);- 响应体自带迁移指引:
DEPRECATED_API_MESSAGE会填入调用方传入的alternatives(替代端点)与开关名,让调用方(包括 Agent 与脚本)无需查文档即可自助迁移。
配套的单测 CompatibilityHelperTest.java 验证了两个分支:开关关闭时抛出带替代信息的异常、开关打开后check(...)放行。
9.2 端点如何接入门控
以 Admin 侧 Pipeline 控制器 PipelineAdminController.java 为例,两个废弃路径参数式端点标注了@Deprecated(since = "3.2.1", forRemoval = true),方法体第一行即调用门控:
/** * Get pipeline execution detail by ID in path. * * @deprecated since 3.2.1, for removal in a future release. Use {@code GET .../detail?pipelineId=}. */ @Since("3.2.0") @Deprecated(since = "3.2.1", forRemoval = true) @GetMapping("/{pipelineId}") @Secured(action = ActionTypes.READ, signType = SignType.AI, apiType = ApiType.ADMIN_API) public Result<PipelineExecution> getPipeline(@PathVariable String pipelineId) throws NacosException { CompatibilityHelper.check( "GET /v3/admin/ai/pipelines/detail?pipelineId={pipelineId}"); return Result.success(pipelineQueryService.getPipeline(pipelineId)); }注意一个细节:门控检查发生在@Secured认证鉴权之后(@Secured由框架切面先执行),因此即使端点被禁用,访问者仍会被正确认证并拿到“指向替代端点”的 410 响应,而不是笼统的 401/403——这保证了迁移期错误信息对认证用户是可消费的。
Console 侧的 ConsolePipelineController.java 做了对称的门控;legacy MCP 导入端点在 ConsoleMcpController.java 中,Javadoc 明确标注 “Planned for removal in Nacos 3.4.0”,与规格第 8 节的移除计划完全吻合。相应地,PipelineAdminControllerTest、ConsolePipelineControllerTest、ConsoleMcpControllerTest以及test/openapi-test下的PipelineAdminApiOpenApiITCase、McpConsoleApiOpenApiITCase等集成测试覆盖了门控开/关两种状态下的响应契约。
9.3 运维开关:nacos.core.api.compatibility.enabled
运维人员可以在迁移期间临时重开全部已接入门控的端点,只需在application.properties中设置:
nacos.core.api.compatibility.enabled=true发行版默认配置 application.properties 中以注释形式给出了该键(默认关闭):
# nacos.core.api.compatibility.enabled=false ### Enabled for legacy open API compatibility provided by nacos-api-legacy-adapter # nacos.core.api.compatibility.client.enabled=true该开关的四条设计约束(规格第 9 节原文要点):
- 有意的共享开关:它只作用于“显式使用了 v3 兼容门控”的 API,即上文表格中的 6 个端点,不是全局兼容总闸;
- 不替代 audience-specific 开关:
nacos-api-legacy-adapter拥有的分受众开关(如配置注释中提到的nacos.core.api.compatibility.client.enabled)不受此影响,两套机制互不越权; - 不绕过安全:重开后认证与鉴权仍然生效(如上所述
@Secured先于业务逻辑执行); - 临时性:定位为“迁移期间临时重开”,不是长期兼容契约。
另一个关键变更:旧的nacos.ai.resource.import.legacy-mcp-api-enabled属性已不再被识别(代码库中检索不到该键的读取逻辑,bootstrap与distribution的application.properties中均已移除);在 插件规格 中,direct user URL 兼容与 legacy MCP 导入适配器本身也被计划于Nacos 3.4.0移除。Legacy MCP 直接 URL 导入现在额外要求nacos.ai.resource.import.allow-user-url=true(默认配置见 application.properties:#nacos.ai.resource.import.allow-user-url=false,即默认关闭),且运维侧应优先使用受管 source 配置——更完整的操作指引可参考 AI 资源导入运维指南。
10. Legacy HTTP API 适配器:v1/v2 出主发行版后的规则
自Nacos 3.2.0 线起,legacy 的 v1 与 v2 HTTP API 不再属于默认 Nacos server 发行版,而是由独立项目nacos-api-legacy-adapter提供,作为一个独立的兼容面。规格为其设定了五条规则:
- v3 HTTP API 与当前 SDK 是规范迁移目标——适配器的存在不改变方向;
- 适配器是临时迁移辅助,不是续命的 API 契约(“not a renewed API contract”);
- 适配器必须显式安装:例如把其 jar 放入 Nacos 的
plugins目录,或作为内嵌/自定义应用的依赖加入; - 适配器版本必须与目标 Nacos server 版本匹配;
- 适配器不保证被未来版本支持,也不是定义新 v1/v2 行为的地方。
对文档的连带要求是:领域规格提及 legacy v1/v2 行为,仅限两种场合——作为迁移上下文,或当前兼容路径确实依赖它。这与配置文件中### Enabled for legacy open API compatibility provided by nacos-api-legacy-adapter的注释相互印证:该注释明确把 adapter 兼容性开关归因于外部适配器,而非 server 自身能力。
11. Legacy A2A Agent 门面:按受众划分的兼容窗口
规范 Agent 模型使用type=agent、协议无关的 Version 与 RAD 发现(详见 A2A Agent 规格、RAD 协议规格 与 Agent 管理规格)。历史 A2A AgentCard 各层表面属于compatibility-only,在服务端边界做适配转换。规格刻意按受众设置了不同的兼容窗口:
| 受众 | 兼容窗口 |
|---|---|
JavaA2aService与 legacy A2A gRPC payload | 尚无移除版本 |
Admin/v3/admin/ai/a2a与A2aMaintainerService | 支持到4.0.x兼容窗口 |
Console/v3/console/ai/a2a | 支持到3.4.x兼容窗口,捆绑 UI 完成迁移后可移除 |
两条边界规则同样重要:不得仅向这些门面添加新能力——新开发一律面向 Agent Management 与 RAD 契约;历史数据迁移与混 server 滚动升级属于独立的迁移计划,不会仅凭它们就延长 API 兼容窗口。
12. Legacy MCP 标识符:mcpId的退役与mcpName的接管
规范 MCP 管理以namespaceId + type=mcp + mcpName三元组标识 Resource。UUID 形态的mcpId作为公开资源标识符已被废弃,但它仍保留两个角色:内部物理存储别名(internal physical-storage alias)与 legacy 线上字段(legacy wire field)。各表面的兼容状态被精确切分:
| 表面 | 状态 | 规则 |
|---|---|---|
| 新的 Admin/Console/Maintainer 生命周期 API | Canonical | 接受mcpName与可选 Version;不再新增mcpId |
| 既有 Admin/Console/Maintainer 的仅 ID 输入 | Deprecated compatibility | 在请求的 Namespace 内解析恰好一个AiResource.ext.mcpId,然后按规范名称鉴权并操作 |
既有 model、event、create/release 响应及嵌套McpServerBasicInfo.id字段 | Active compatibility | 在物理 Config 坐标与当前消费者仍需其存在期间,保持线上结构与取值不变 |
MCP gRPC 请求中顶层AbstractMcpRequest.mcpId | Ignored and deprecated | 保留其字段编号(field number),不实现 ID 查找,各 handler 维持当前的 name 要求 |
工程上最严格的一条是 legacy ID 查找的实现限制:不允许使用最终一致性的 Search、不允许使用历史 Manifest/Config 身份查找、不允许建立 MCP 专用的内存索引,也不为此废弃路径新增任何表或列。这从实现层面杜绝了“兼容路径悄悄长出第二套真相来源”的风险。移除mcpId需要一次独立的迁移(涵盖 Config 坐标、直连消费者、SDK 模型与线上响应),且首次承载生命周期的迁移不定义移除版本;精确行为归属 MCP Server 规格。
12.1 Legacy MCP Maintainer 方法的废弃与迁移对照
legacyMcpMaintainerService的 detail 与 direct-online 创建/更新方法自Nacos 3.3.0 起废弃,计划于 Nacos 4.0.0 移除,兼容窗口内运行时行为保持不变。调用方应按以下对照迁移:
| 废弃操作 | 规范替代 |
|---|---|
| Serving 投影 detail | 用listMcpServerVersions选定精确 Version,再用getMcpServerVersion获取 |
| local/remote/泛化的 direct-online 创建 | 先createMcpServer(McpServerDraftRequest),再submitMcpServerVersion;若适用评审,批准后显式publishMcpServerVersion |
| Direct-online 更新 | 新版本用createMcpServer(McpServerDraftRequest),已有草稿用updateMcpServer(McpServerDraftRequest),随后 submit,必要时 publish |
同时规格划出了一条“暂不废弃”的边界:legacy 跨资源 list/search 与 published-Version 或 full-Resource 删除方法未被本次决策废弃——因为类型化生命周期表面尚未提供语义等价的替代,必须先经过独立的 API 设计与废弃评审才能设定移除版本。这体现了该规格的一贯立场:没有等价替代,就不宣布废弃。
13. 总结与延伸阅读
这份兼容与废弃规格的本质,是把“哪些东西还活着、活到什么时候、往哪里迁移”从各模块的隐性约定,提升为一套可审计、可测试、可执行的治理制度:六态模型负责分类,文档规则防止静默删除,ability-gated fallback 约束混版本回退,存储与插件规则防止兼容字段语义漂移,而CompatibilityHelper门控与 legacy 适配器则把制度落实到 HTTP 410 响应与发行版边界上。
延伸阅读(均在仓库specs/en/下):
- HTTP API 规格 与 V3 API Surface:废弃端点在兼容章节中的具体呈现;
- SDK 规格:SDK 二进制兼容与规范接口引导;
- 客户端能力协商规格:ability-gated fallback 的协商基础;
- 资源模型规格 与 持久化与 Dump 规格:存储兼容字段规则的上位依据;
- 集成与适配器规格:适配器兼容面的通用规则;
- MCP Server 规格:
mcpId兼容行为的精确领域定义; - AI 资源导入运维指南:导入端点迁移的操作侧文档。
【免费下载链接】nacosan easy-to-use dynamic service discovery, configuration and service management platform for building AI cloud native applications.项目地址: https://gitcode.com/GitHub_Trending/na/nacos
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考