Files
alibaba--nacos/specs/zh-cn/plugin/plugin-spec.md
T
2026-07-13 12:37:52 +08:00

14 KiB
Raw Blame History

Nacos 插件化规范

目的

Nacos 使用插件机制和 SPI 扩展,将横切基础能力和可替换的领域能力从固定核心中拆出。 插件可以提供鉴权、资源可见性、数据源方言、加解密、链路追踪、流量控制、环境适配、 AI pipeline、AI 存储、AI 资源导入或 Java 客户端侧请求适配等能力。

插件机制的目标,是在保持 Nacos 核心模型稳定的同时,让不同部署环境可以选择符合自身 身份系统、数据库、观测体系或扩展场景的实现。

插件身份

每个插件由以下字段唯一标识:

  • pluginType:扩展类别,例如 authvisibility
  • pluginName:该类别下的实现名称,例如 nacos
  • pluginId:运行时标识,格式为 {pluginType}:{pluginName}

pluginId 用于管理 API、集群状态同步、插件状态持久化和面向用户的诊断信息。

插件类型

当前插件类型注册表由 PluginType 定义。

类型 目的 契约
auth 认证与授权实现。 鉴权插件规范
visibility 资源可见性与查询可见性建议。 可见性插件规范
datasource-dialect 数据库方言与持久化适配。 数据源方言插件规范
config-change 配置变更扩展。 配置变更插件规范
encryption 加解密扩展。 配置加密插件规范
trace 链路追踪与观测扩展。 Trace 插件规范
environment 环境适配扩展。 环境插件规范
control 流量与控制扩展。 Control 插件规范
ai-pipeline AI 注册中心 pipeline 扩展。 AI 发布 Pipeline 插件规范
ai-storage AI 注册中心存储扩展。 AI 存储插件规范
ai-resource-import AI 注册中心外部资源导入扩展。 AI 资源导入插件规范

各插件类别的领域契约由对应规范定义。本文档定义所有插件类别共享的运行时契约。

寻址扩展为了和公开插件文档保持连续性,也放在插件 规范中记录;但当前服务端代码通过 MemberLookup 处理寻址,并未将其注册到 PluginType

运行位置

Nacos 有两类插件式扩展面:

运行位置 加载模型 状态归属 示例
服务端插件 领域 SPI 加 PluginProvider,在支持时可由服务端插件 API 列出和管理。 Nacos 服务端进程;对可管理插件,还包括服务端插件状态。 authvisibilitydatasource-dialectcontroltrace
Java 客户端扩展 在客户端进程内通过 Java SPI 或 SDK API 加载。 客户端 classpath、客户端配置和 SDK 实例生命周期。 ServerListProviderClientAuthServiceIConfigFilter、客户端侧配置加密。

客户端扩展不由 /v3/admin/core/plugin/* 管理,也不具备服务端 PluginStateCheckerHolder 决策,除非对应服务端插件同时参与请求处理。它们仍必须遵守 Nacos 资源身份、鉴权和 payload 语义,因为它们会影响 SDK 发出的请求。

执行形态

插件类别并不都以同一种形态执行。每个插件类型都必须明确自身执行形态。

形态 含义 示例
互斥选择 在进程或请求范围内选择一个实现,其他已加载实现不参与该次判断。 authdatasource-dialect
配置选择的单服务 可以加载多个实现,但领域根据配置或请求上下文选择一个服务。 visibilityai-resource-import
有序链式执行 多个匹配插件按稳定顺序执行。每个节点可以贡献结果,失败是否中断由领域定义。 ai-pipelineconfig-change
订阅或广播 多个订阅者观察同一个事件或 trace 点,不拥有主决策权。 trace、事件型扩展

对于链式插件,领域 SPI 必须定义:

  • 如何根据资源或 pointcut 选择候选插件。
  • 哪个字段控制顺序,例如 getPreferOrder()getOrder()
  • 执行方式是串行还是并行。
  • 某个插件失败时,是中断链路还是只记录失败结果。
  • 如何持久化和暴露部分执行结果。

核心插件管理器记录插件的加载状态和启用状态,本身不定义执行形态。领域管理器负责稳定地 应用对应执行形态。

SPI 层次

Nacos 插件包含两个相关的 SPI 层次:

  1. 领域 SPI,例如 AuthPluginServiceVisibilityService,定义所属领域需要的行为。
  2. 核心插件 SPI,即 PluginProvider,将插件实例暴露给核心插件管理器,用于列表查询、 状态管理、配置管理和运行时观测。

需要动态配置的插件应实现 PluginConfigSpec。支持启停状态判断的插件类别,应通过 PluginStateCheckerHolder 获取状态,而不是维护一套独立状态来源。

加载与生命周期

插件实现通过 Nacos SPI 加载。部署时可以从 classpath 或服务端插件目录提供插件。 插件实现必须能在不修改 Nacos 服务端代码的情况下被加载。

核心 PluginManager 会在服务端应用就绪后发现 PluginProvider 实现。领域管理器也可以 通过 SPI 加载自身领域服务,但是否可参与请求处理,仍必须遵守核心插件管理器维护的启停 状态。

插件启动必须具备确定性:

  • 一个插件类型和插件名称组合只能对应一个运行时插件实例。
  • 同一插件类型下重复的插件名称不适合稳定运行。
  • 插件实现不得改变 Nacos 共享资源标识、响应封装或错误约定的含义。

状态与配置

插件状态分为两个层次:

  • 已加载:实现存在于运行时。
  • 已启用:实现可以参与请求处理。

大多数插件类型在加载后默认启用。互斥插件类型会选择一个默认实现:

类型 默认选择规则
auth nacos.core.auth.system.type 指定,默认 nacos
datasource-dialect 由 SQL platform 配置指定,默认 derby

当服务端依赖某些插件维持基本运行能力时,这些插件不能被禁用。当前关键插件集合包括内置 数据源方言,以及服务端需要的默认 AI 存储插件。

实现 PluginConfigSpec 的插件应暴露配置定义、当前配置和配置应用行为。除非请求明确 声明为仅本机生效,否则集群级状态或配置变更必须通过插件状态操作链路进行同步。

配置定义

插件配置项由 ConfigItemDefinition 描述。key 表示插件实现内部的 canonical item key,不携带 nacos.plugin.{pluginType}.{pluginName}. 前缀。静态配置推荐使用以下 normalized full key

nacos.plugin.{pluginType}.{pluginName}.{itemKey}

配置定义可以声明以下元数据:

字段 含义
aliases 历史静态配置 key,用于兼容读取和迁移提示。
sensitive 是否为敏感值。查询 API 返回前必须脱敏。
effectMode 生效模式,RUNTIME 表示可运行时生效,RESTART 表示需要重启。

aliases 用于静态配置兼容读取,也可以作为迁移兼容的 API 输入。完成归一化后,alias 不应写入运行时持久化文件或 local-only 内存表。如果输入同时包含同一配置项的多个 alias,则按定义中的声明顺序取第一个生效,并由服务端记录其余 alias 被忽略的日志。

配置来源与值元数据

插件配置的 effective value 由统一解析流程计算。配置来源优先级为:

LOCAL_ONLY > RUNTIME_PERSISTED > STATIC > DEFAULT
来源 含义
DEFAULT 来自 ConfigItemDefinition.defaultValue
STATIC 来自 application.properties、环境变量、JVM 参数或 Spring 参数等静态配置。
RUNTIME_PERSISTED 来自集群级运行时 override,当前可由 plugin-configs.json 记录终态内容。
LOCAL_ONLY 当前节点的本机 override,只用于诊断或应急处理,不同步到集群。

插件详情返回模型可以追加以 canonical item key 为索引的 configValueMetas map。每个 PluginConfigValueMeta 用于描述对应配置项的当前值来源和是否存在多来源覆盖。 overridden 忽略 DEFAULT,只有同一 key 同时存在多个非默认来源时才应为 true

运行时持久化配置和 local-only 配置只保存 pluginId + itemKey 对应的值,不保存 normalized full key、alias key、source 或版本信息。

每个内部 source resolver 都必须通过 getConfig(PluginInfo) 返回使用 canonical item key 的完整 map。读取能力与写入能力相互独立:DEFAULT 从 definition 读取默认值, STATIC 根据标准 key 和 alias 从环境读取,两个运行时 source 读取各自内部 map。 isUpdatable 只在替换 source map 时检查。每次更新完整替换该 source 的 map;传入空 map 表示清空该插件在该 source 下的全部 override,不额外提供 remove 或 restore 操作。

配置更新兼容性

插件详情 API 应保持 additive 兼容:已有 configconfigDefinitions 字段继续 保留,其中 config 可以表示当前 effective config,新增的 configValueMetas map 按 canonical item key 提供 source 和 overridden 等元信息。

PUT /v3/admin/core/plugin/config 和对应 Console API 保持现有完整 override map 更新语义。localOnly=true 表示只更新当前节点 local-only override;否则更新集群级 runtime persisted override。key 归一化和 effectMode 校验由服务端内部完成,不作为 新的 API 参数暴露。effectMode=RESTART 的字段不应通过运行时更新立即生效。 服务端应比较目标 source 更新前后的完整 map,因此新增、修改或移除 RESTART 配置项 都必须拒绝。提交的完整 map 中省略某个 key,只有在该配置项支持运行时生效时才表示 移除对应 override。 canonical item key、normalized full key 和兼容 alias key 应在校验及存储前统一归一化为 item key。请求包含未定义 key,或者 alias 歧义命中多个配置项时,应返回参数校验错误。

对于声明为 sensitive=true 的配置项,提交值只要包含统一的 ****** marker,就按 脱敏展示值处理。如果当前目标 source 已经包含该 key,服务端应保留该 source 中的原始 值;如果目标 source 不包含该 key,则忽略这项输入,继续保持该 source 不存在此 key。 该判断同时覆盖 ******a******zab******yz,且不得把 STATIC 等其他 source 的 effective value 复制成 runtime override。服务端应记录 WARN 日志,但只记录 pluginId、item key 和目标 source,不得打印配置值。

初始化与运行时应用

启动和运行时更新复用同一套 source resolver 与 effective config 计算逻辑:

  1. 启动时先将 plugin-configs.json 中的全部内容装载到 runtime persisted source 再开始应用插件配置。
  2. 随后对每个已加载的可配置插件执行 resolve 和 apply,即使该插件没有持久化 override 也要处理。启动属于初始化阶段,可以同时应用 RUNTIMERESTART 字段。
  3. 运行时请求完整替换一个 RUNTIME_PERSISTEDLOCAL_ONLY source map,随后 重新解析全部来源;每次接受的请求都调用插件实现,包括使用相同完整 map 发起的 手动重试。

同一插件的更新应串行执行。runtime persisted 更新先持久化归一化后的完整 source map,再替换 resolver source、解析并校验 effective config,最后应用到插件。持久化 失败时不得修改 resolver source 或插件,也不执行回滚。source 更新成功但 apply 失败 时,已接受的 source map 保持持久化和可解析状态,服务端不自动发起回滚或补偿更新; API 应明确返回“配置已更新但 apply 失败”的服务端错误,日志记录 plugin ID 和 source 且不记录配置值。再次提交相同完整 map 可以手动重试 apply。LOCAL_ONLY 更新执行相同 的 replace、resolve、apply 流程,但不持久化、不同步;apply 失败后新的本机 source map 同样保留。

管理 API

核心插件管理 API 如下:

方法 路径 目的
GET /v3/admin/core/plugin/list 查询已加载插件,可按类型过滤。
GET /v3/admin/core/plugin/detail 查询单个插件详情,返回 effective config 和可选值元数据。
PUT /v3/admin/core/plugin/status 启用或禁用插件。
PUT /v3/admin/core/plugin/config 更新插件配置。

这些端点属于 Admin API,并要求符合 HTTP 鉴权规范 中的控制台域鉴权。插件管理 API 必须使用标准 v3 响应与错误模型

设计要求

插件实现必须遵守以下规则:

  • 使用已有 Nacos 资源标识和领域模型,不为同一 资源发明不兼容的新模型。
  • 插件提供的 HTTP API 必须保持 v3 HTTP API 响应、错误和 鉴权约定。
  • 仅通过 PluginConfigSpec 暴露插件自身拥有的配置。
  • 除调用方明确要求本机操作用于诊断或应急处理外,集群级状态变更必须保持同步。
  • 安全敏感的默认值和部署要求必须在插件实现规范中说明。

插件机制是扩展边界,不是绕过 Nacos 资源、API 或安全规则的通道。