news 2026/9/11 14:43:45

Nacos Java SDK Agent 代码发布(Code-First Publication)集成测试场景全解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Nacos Java SDK Agent 代码发布(Code-First Publication)集成测试场景全解析

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携带的字段即完整请求体:

字段类型含义
agentNameStringAgent 唯一标识(必填)
displayNameString展示名
descriptionString描述
iconUrlString图标地址
providerAgentProvider提供方信息(name/url)
tagsList<String>标签
extensionsMap<String,Object>扩展信息
versionString精确版本号(必填)
callInterfacesList<AgentCallInterface>直接内容(二选一)
authorString作者
changeDescriptionString变更说明
basedOnVersionString基于某个已有版本继承内容(二选一)
autoSubmitboolean是否在草稿创建后自动走普通提交管线

关键语义(源码 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):draftreviewingreviewedonlineoffline

内容来源校验在AgentDraftCreateRequest.validate()中实现(见 api/src/main/java/com/alibaba/nacos/api/ai/model/agent/AgentDraftCreateRequest.java):callInterfacesbasedOnVersion必须且只能出现一个,否则抛出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_FOUNDgetAgentCard(agentName)同样 NOT_FOUND。
  • SDK 不得篡改调用方请求:测试在发布前后对请求做JacksonUtils.toJson快照对比,保证对象引用级别的所有权不被破坏。

3.autoSubmit=true:一次成文直接上线

  • 首次请求即创建并提交首个直接内容版本;无审核 Pipeline 时状态为online
  • RAD Discover 与旧版 A2A 查询此时都能拿到同一个 A2A 描述符discoverAgent返回1.0.0版本与onlinecontentDigest一致;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 使用basedOnVersionINVALID_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_MODEnacosAiTransportMode)控制,取值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受控失败。

运行前提:

  1. 先启动 standalone 模式的 Nacos 服务器(nacosServer相关启动入口见仓库根目录 README.md 与 distribution/conf/application.properties)。
  2. 测试客户端通过JavaSdkBaseITCase.sdkProperties()连接服务器,CONTEXT_PATH设为/nacos
  3. 可选指定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(服务端主动推送)
  • 本地getAllselectOneHealthy辅助方法
  • 管理元数据订阅(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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 14:40:22

ClickHouse MergeTree家族全解析:排序键、分区键与引擎选型实战

1. 从 MergeTree 的核心设计聊起如果你用过 ClickHouse&#xff0c;那大概率绕不开 MergeTree。很多刚接触 ClickHouse 的人会把 MergeTree 当成“一种表引擎”&#xff0c;但严格来说&#xff0c;它是一个庞大的家族&#xff0c;官方文档里叫 MergeTree Family。这个家族的共同…

作者头像 李华
网站建设 2026/9/11 14:37:50

Docker日志导出全攻略:从存储机制到轮转配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 14:36:25

res-downloader 完整指南:视频号无水印、抖音、m3u8 与直播流一次搞定

res-downloader 完整指南&#xff1a;视频号无水印、抖音、m3u8 与直播流一次搞定 【免费下载链接】res-downloader 视频号、小程序、抖音、快手、小红书、直播流、m3u8、酷狗、QQ音乐等常见网络资源下载! 项目地址: https://gitcode.com/GitHub_Trending/re/res-downloader …

作者头像 李华
网站建设 2026/9/11 14:33:50

NSGA-Ⅲ算法在电力系统多目标调度中的实践与优化

1. 项目背景与核心挑战在电力系统调度领域&#xff0c;梯级水电与火电机组的联合调度一直是个经典难题。我十年前第一次接触这个课题时&#xff0c;就被其复杂的多目标特性所吸引——既要满足电网负荷需求&#xff0c;又要兼顾水能利用率、煤耗成本、排放控制等多个相互冲突的目…

作者头像 李华