Nacos Java SDK Agent 代码发布(Code-First Publication)集成测试场景全解析
【免费下载链接】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 仓库中 AGENT_PUBLISH_SDK_IT_SCENARIOS.md 记录的 Agent 代码发布(Code-First)Java SDK 集成测试场景矩阵展开,系统梳理AiService.publishAgent公开契约、autoSubmit草稿/在线状态机、版本演化与冲突规则、RAD/旧版 A2A 双投影一致性,以及旧版A2aService端点预注册与订阅恢复等关键行为。读者阅读本文后,将掌握如何用 Nacos Java SDK 以纯代码方式发布 Agent 定义、理解草稿—提交—在线各状态下的可观察性与错误码语义,并能在 gRPC/HTTP 双传输、命名空间隔离、多版本端点预注册等真实场景中编写可复现的集成测试。
注:本文所有测试矩阵、断言与源码引用均以当前仓库实际内容为准,场景验证代码位于 test/java-sdk-test/src/test/java/com/alibaba/nacos/test/sdk/ai/AgentPublishJavaSdkITCase.java。
一、场景矩阵总览:为什么需要 Code-First 发布
在 Nacos 3.x 的 AI 资源体系中,Agent 的定义(AgentCard、callInterfaces、端点等)既可以通过控制台/管理端录入,也可以由应用代码直接发布。本文档所记录的正是第二种路径——代码优先(Code-First)定义发布,其对外契约是公开的AiService.publishAgent(AgentPublishRequest)方法(见 api/src/main/java/com/alibaba/nacos/api/ai/AiService.java),自 Nacos 3.3.0 起提供。
场景矩阵分为三大板块:
| 板块 | 覆盖范围 |
|---|---|
| Code-First 定义发布 | autoSubmit=false/true、续提(Resume)、重试收敛、冲突与状态机、版本演化、命名空间隔离、传输等价性、端点独立性 |
| 旧版 A2aService 一版对齐 | 端点预注册、多版本重做、重放快照隔离、精确/latest 路由、重新订阅、优雅关闭 |
| 复合跨面工作流 | 通用 SDK 发布 + RAD/Console/旧版 A2A 交叉读取、定义与端点发布顺序、多版本演进订阅、HTTP/gRPC 双向交叉 |
所有测试以外部 Java 客户端身份连接独立(standalone)服务器运行,保证场景与真实生产调用链一致。
二、Code-First 定义发布核心契约
1.publishAgent请求模型与默认行为
AgentPublishRequest继承自AgentDraftCreateRequest,仅增加一个autoSubmit布尔字段(见 api/src/main/java/com/alibaba/nacos/api/ai/model/agent/AgentPublishRequest.java)。父类AgentDraftCreateRequest携带的字段即完整请求体:
| 字段 | 类型 | 含义 |
|---|---|---|
agentName | String | Agent 唯一标识(必填) |
displayName | String | 展示名 |
description | String | 描述 |
iconUrl | String | 图标地址 |
provider | AgentProvider | 提供方信息(name/url) |
tags | List<String> | 标签 |
extensions | Map<String,Object> | 扩展信息 |
version | String | 精确版本号(必填) |
callInterfaces | List<AgentCallInterface> | 直接内容(二选一) |
author | String | 作者 |
changeDescription | String | 变更说明 |
basedOnVersion | String | 基于某个已有版本继承内容(二选一) |
autoSubmit | boolean | 是否在草稿创建后自动走普通提交管线 |
关键语义(源码 Javadoc 明示):
- 默认只建草稿:
autoSubmit缺省为false,服务端仅创建draft状态版本,不会直接对外暴露。 autoSubmit=true不是 force-publish:它触发的是普通提交管线(submit pipeline),如果配置了审核 Pipeline,版本会停留在reviewing;只有无审核管线时才会直接变为online。
AiConstants中定义的版本状态机为(见 api/src/main/java/com/alibaba/nacos/api/ai/constant/AiConstants.java):draft→reviewing→reviewed→online→offline。
内容来源校验在AgentDraftCreateRequest.validate()中实现(见 api/src/main/java/com/alibaba/nacos/api/ai/model/agent/AgentDraftCreateRequest.java):callInterfaces与basedOnVersion必须且只能出现一个,否则抛出IllegalArgumentException,对应集成测试中的NacosException.INVALID_PARAM断言。
2.autoSubmit=false:草稿发布与不可见性
场景断言要点(对应测试方法 AgentPublishJavaSdkITCase.java):
- 首次调用
publishAgent后返回的AgentVersionDetail.status == "draft",namespaceId为请求方 AiService 的命名空间。 - Admin 与 Console 读取到相同内容与 digest:SDK 侧通过
maintainer.getAgentVersion(...)与发布结果做 digest 一致性校验。 - RAD Discover 与旧版 A2A 查询均不暴露草稿:
discoverAgent(reference)抛出NacosException.NOT_FOUND,getAgentCard(agentName)同样 NOT_FOUND。 - SDK 不得篡改调用方请求:测试在发布前后对请求做
JacksonUtils.toJson快照对比,保证对象引用级别的所有权不被破坏。
3.autoSubmit=true:一次成文直接上线
- 首次请求即创建并提交首个直接内容版本;无审核 Pipeline 时状态为
online。 - RAD Discover 与旧版 A2A 查询此时都能拿到同一个 A2A 描述符:
discoverAgent返回1.0.0版本与online的contentDigest一致;getAgentCard(agentName, version, A2A_ENDPOINT_TYPE_URL)返回相同 name/version,且supportedInterfaces包含 2 个接口(HTTP+JSON 与 GRPC)。
4. Resume:草稿续提而不产生重复版本
先以autoSubmit=false发布草稿,再以等价请求(仅autoSubmit改为true)重复提交:服务端复用已有草稿并提交,不会创建重复版本,返回的contentDigest与草稿完全一致。这正是发布场景中"先审后发、审完一键上线"的典型用法。
5. 重试收敛(Retry Convergence)
- 等价的
false重试:返回既有草稿,幂等。 - 等价的
true重试(已在线):返回既有版本,不重复创建。 - 提交结果二义性后的重试:通过重新读取状态收敛(而非盲目重放),由 Java SDK IT + 服务端单元故障注入共同覆盖。
6. 冲突与状态机(Conflict and State)
| 冲突情形 | 期望错误码 |
|---|---|
| 相同精确版本号、内容不同 | NacosException.CONFLICT |
| 相同版本、author 不同 | CONFLICT |
| 相同版本、changeDescription 不同 | CONFLICT |
| 显式提供初始元数据不一致 | CONFLICT |
对已上线版本以autoSubmit=false提交 | CONFLICT(不覆盖) |
| 对 offline 版本以任一模式提交 | INVALID_PARAM(不覆盖) |
测试中对相同请求重放(draftOnlyRetry)直接断言CONFLICT,说明"完全等价请求的重试收敛"与"内容/元数据变更请求"是区分对待的:前者幂等返回既有版本,后者报冲突。
7. 版本演化(Version Evolution)
- 发布后续直接内容版本(direct-content Version):每个版本各自持有内容,digest 不同。
- 发布
basedOnVersion继承版本:新版本复制被继承版本的内容,因此contentDigest与被继承版本一致,但版本号不同,RAD Discover 指向新版本号。 - 拒绝首版本继承:对全新 Agent 使用
basedOnVersion报INVALID_PARAM。 - 拒绝"两源皆无/两源皆有":既不带
callInterfaces又无basedOnVersion,或两者同时出现,均报INVALID_PARAM(源码validate()中directContent == copiedContent即命中)。
8. 命名空间与调用方隔离
- 默认命名空间与自定义命名空间完全隔离:自定义命名空间发布的 Agent,在默认命名空间的 gRPC 客户端上
discoverAgent返回NOT_FOUND。 - 请求不能自行指定命名空间:命名空间取自 AiService 客户端本身(
PropertyKeyConst.NAMESPACE)。 - SDK 拷贝语义:发布请求的每个调用方持有字段与嵌套值在往返中保持不变,由代理单元测试(proxy unit tests)覆盖深拷贝与不可变性。
9. 传输等价性(Transport Parity)
- 同一请求与错误类别在显式选择 gRPC 与 HTTP 传输时行为一致:gRPC 发布的 Agent 可在 HTTP 客户端上 Discover,且 HTTP 客户端以相同请求再次发布返回相同 digest(幂等)。
- 未协商的能力在本地即失败:不支持的能力不会发出远程请求,直接本地抛错(对应
NacosException.SERVER_NOT_IMPLEMENTED一类语义)。 - 传输模式由
AiConstants.AI_TRANSPORT_MODE(nacosAiTransportMode)控制,取值grpc/http/auto(见 AiConstants.java),测试中通过Properties注入AiConstants.AI_TRANSPORT_MODE创建客户端。
10. 端点独立性(Endpoint Independence)
- 定义前预注册端点可以成功,且不会创建 Agent 定义(
getAgentCard仍 NOT_FOUND)。 - 定义优先(definition-first)与端点优先(endpoint-first)两条工作流在发布后收敛到同一结果:RAD 与旧版 SERVICE 查询都能解析出同一个精确版本对应端点。
三、旧版 A2aService 一版对齐(Legacy Alignment)
该板块保证旧版A2aService(RAD 出现前的 AgentCard 查询/订阅接口)与新的代码发布契约在第一版本语义上对齐。
1. 端点预注册(Endpoint Pre-registration)
- 先将旧版精确版本端点
registerAgentEndpoint(agentName, endpoint)注册进规范 Runtime Service,此时定义查询仍为空。 - 再发布 AgentCard:RAD Discover 与旧版 SERVICE 查询(
A2A_ENDPOINT_TYPE_SERVICE)同时暴露预注册端点。 - 测试通过
containsLegacyEndpoint校验 URL(http://{address}:{port}{path})、transport(JSONRPC)与 protocolVersion 全部匹配;端点默认 transport 见 AiConstants.java。
2. 多版本重做(Multi-Version Redo)
一个 SDK 以两个独立"规范子发布者"身份为两个精确版本发布旧版端点,然后真实重启 standalone 服务器,重启后两个 Runtime 绑定均恢复,且不会覆盖父连接上的协议中立发布(protocol-neutral publication)。该场景是"服务端重启后旧版端点绑定可恢复"的定向 Java SDK IT。
3. 重放快照隔离(Redo Snapshot Isolation)
注册之后再修改调用方原始 Endpoint 对象或集合,不会改变重放(replay)载荷——即发布请求在注册瞬间完成快照拷贝,由聚焦客户端单元测试覆盖。
4. 精确/latest 路由
- 精确订阅:即使该版本恰为 latest,精确订阅者也能收到变更。
- latest 订阅:即使目标精确版本已在缓存中,latest 指针移动事件依然会下发。
- 测试覆盖"latest 从 v3 回退到已缓存的 v2"(
offlinev3 后 latest 指针移动)等确定性场景,配合缓存/通知器单元测试。
5. 重新订阅(Resubscribe)
取消订阅后再以已缓存值重新订阅:轮询会重新启动,且能观察到后续变更(如 v4 发布后收到事件)。集成测试用CountDownLatch+AbstractNacosAgentCardListener断言事件到达,轮询超时 25 秒。
6. 关闭(Shutdown)
反复调用 SDKshutdown():停止旧版 AgentCard 轮询、释放 executor,且关闭后不再产生任何回调,由 Java SDK IT + 生命周期单元测试覆盖。
四、复合跨面工作流(Compound Cross-Surface Workflows)
| 工作流 | 交叉校验内容 |
|---|---|
通用 SDK 以autoSubmit=true发布 A2A,再经 RAD Search/Discover、Console/Admin、旧版 A2A 读取 | 所有投影共享同一规范定义、精确版本、描述符、声明端点与 digest |
| 旧版端点先行、通用 SDK 定义后行 | 端点发布永不创建定义;定义发布后 RAD 与旧版 SERVICE 查询解析出同一规范 Runtime 端点与绑定 |
| 通用 SDK 发布 v1 → 注册运行时端点 → 订阅 latest → 发布 v2 → 注册 v2 端点 | Search、精确/latest Discover、轮询订阅、旧版 A2A 查询、旧版订阅在每个迁移点收敛 |
| HTTP 发布 + gRPC Discover,随后 gRPC 发布 + HTTP Discover | 定义状态与错误映射传输等价;持久化定义发布不需要 Publisher 心跳身份 |
最后一行尤为重要:它明确了本阶段的边界——Server Watch/Push、本地getAll/selectOneHealthy辅助方法、管理元数据订阅、滚动升级、数据迁移、双写(dual writes)与 force-publish 均不在本阶段范围之内,属于后续阶段能力。
五、如何运行与复现这些场景
场景全部以 JUnit 5 集成测试形式存在于 test/java-sdk-test 模块,关键用例:
- AgentPublishJavaSdkITCase.java:草稿/续提/冲突/版本演化/命名空间/传输等价/端点预注册/路由与重订阅/关闭等全部核心断言。
- AiTransportResourceMatrixJavaSdkITCase.java:以
grpc/http/auto三种模式对 Agent、MCP、Prompt、Skill、AgentSpec 五大 AI 资源族做传输矩阵验证,其中 Agent 部分验证publishAgent后 Search/Discover/订阅/运行时端点注册全链路,并断言 Skill/AgentSpec 在 gRPC 模式下的SERVER_NOT_IMPLEMENTED受控失败。
运行前提:
- 先启动 standalone 模式的 Nacos 服务器(
nacosServer相关启动入口见仓库根目录 README.md 与 distribution/conf/application.properties)。 - 测试客户端通过
JavaSdkBaseITCase.sdkProperties()连接服务器,CONTEXT_PATH设为/nacos。 - 可选指定
nacosAiTransportMode=grpc|http|auto验证传输等价性。
复现要点(从测试代码提炼的最小客户端配置):
Properties properties = new Properties(); properties.setProperty(PropertyKeyConst.SERVER_ADDR, "127.0.0.1:8848"); properties.setProperty(PropertyKeyConst.NAMESPACE, namespaceId); // 命名空间隔离 properties.setProperty(AiConstants.AI_TRANSPORT_MODE, "grpc"); // grpc | http | auto AiService service = AiFactory.createAiService(properties); // 参见 api 模块工厂 AgentVersionDetail detail = service.publishAgent(request); // Code-First 发布六、边界与阶段声明(Out of Scope)
按 AGENT_PUBLISH_SDK_IT_SCENARIOS.md 末尾声明,以下能力不在本阶段覆盖:
- Server Watch / Push(服务端主动推送)
- 本地
getAll或selectOneHealthy辅助方法 - 管理元数据订阅(management metadata subscription)
- 滚动升级(rolling upgrade)、数据迁移(data migration)、双写(dual writes)
- force-publish(强制发布)
这些能力将在后续阶段补齐,本阶段聚焦"代码发布 + 双投影一致性 + 旧版对齐"这一最小可用闭环。
结语
AGENT_PUBLISH_SDK_IT_SCENARIOS.md所记录的场景矩阵,本质上是 Nacos AI 注册中心"代码优先定义发布"的可验证契约:以AiService.publishAgent为入口,以autoSubmit为草稿/在线状态开关,以 digest 为一致性锚点,同时保证 RAD 与旧版 A2A 双投影共享同一规范定义,并以严格的冲突/错误码语义守住版本不可变与命名空间隔离。对于需要以纯代码方式注册 AI Agent 的开发者,这套场景即是最权威的契约说明书与回归测试清单。
【免费下载链接】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),仅供参考