← 返回藏书阁

A2A Jakarta:跨节点状态复制不等于生产安全与故障恢复

wiki/ai/sources/a2a-jakarta-cross-node-state-and-effective-security.md
分类:ai / sources · 更新:2026-09-13 09:16

A2A Jakarta:跨节点状态复制不等于生产安全与故障恢复

知识点轴:A2A / harness-runtime / sandbox-security。 价值不是又一个 SDK release,而是一个可逐文件核对的双节点案例:共享持久状态与复制实时事件各司其职;SDK 的安全默认值,却被示例配置主动关闭。

为什么值得深挖

Hermes 若把长任务委托给远端 agent,断流后的客户端可能连接到另一实例。单机 TaskHandle 能拿到任务 ID,不代表新节点知道历史状态、能收到后续事件或能安全继续工作。此案例把 A2A-Agent2Agent-Protocol 的任务协议落到 Harness-Engineering 的状态/事件基础设施,比仅可读 Agent Card 多了一层工程证据;不是用户系统的部署推荐。

来源与版本边界

  • WildFly 公告 发布于 2026-09-10,声明 Jakarta 1.0.0.Final 支持 A2A 1.0、JSON-RPC/gRPC/REST 和 0.3 兼容层。
  • 固定仓库 wildfly-extras/a2a-jakarta,commit d611c7c336948c12dab20f4e46d324a22a492e41。根 pom.xmlversion.sdk=1.3.2.Finalversion.wildfly=41.0.1.Final 与公告一致。
  • 文档争议:同 tag 根 README 仍写 SDK 1.0.0.Final。本页按 POM/公告记录依赖版本,保留 contested: true 提醒文档未同步;未执行 dependency resolution,所以不是实际 WAR 依赖清单。
  • 已读公告、上游 1.3.0 安全迁移说明、企业 README、Card/executor/client、配置及一个多租户 JSON-RPC 测试包装类。GitHub API 限流,未取得可靠当前 star 数;不影响固定 tag 代码取证。^[raw/articles/a2a-jakarta-cross-node-state-and-effective-security-2026-09-13.md]

机制:状态存储、事件传播和执行恢复是三件事

  1. 状态面:两个 WildFly 节点共用 PostgreSQL;JPA TaskStorePushNotificationConfigStore 替换内存实现,保存任务及推送配置。示例使用非破坏性 schema update,不应将启动 B 等同重建 A 的库。
  2. 事件面:Kafka-backed ReplicatedQueueManager 传播 live events。示例要求每节点独立 group.id,让 A/B 都收到同一 topic 的事件;共享 consumer group 的分摊消费不能直接替代这一广播语义。
  3. 演示路径:客户端从 A/B 各自解析 Card;向 A 发 messageId="init" 建任务,在 B subscribeToTask,再向 A 发带同一 taskId 的 continuation。A 产生 working → artifact → completed,B 收集状态与产物。init 是 executor 明写的 demo-only 约定,不是 A2A 标准握手
  4. 恢复面未证明:A 仍负责实际执行,B 是观察者。本路径没有展示 A 宕机后的工作接管、业务动作幂等或跨节点取消。因此共享 task DB + 事件复制不推出执行 exactly-once 或 HA 完成保证。^[raw/articles/a2a-jakarta-cross-node-state-and-effective-security-2026-09-13.md]

这与 a2a-query-task-handle-approval-broker 互补:后者强调客户端状态句柄/重订阅,本文补服务端跨节点的共享状态与事件传播。MCP-Gateway-Runtime 的负载均衡或 session affinity 只能选路,不能替代任务状态协议。

最重要反例:默认值与有效配置相反

上游 1.3.0 公告称未配置 TaskAuthorizationProvider 时默认拒绝任务操作,并将检查移入 DefaultRequestHandler 覆盖 CDI/builder 路径。这是 SDK 公告层证据,不是本机对实现的安全审计。固定 tag 的企业示例却明确配置 a2a.authorization.required=false 把「SDK fail-closed」与「企业示例」两句话拼在一起,会制造不存在的授权保证。^[raw/articles/a2a-jakarta-cross-node-state-and-effective-security-2026-09-13.md]

多租户 MultiTenantJsonRpcTest 继承上游抽象测试并加载专用 fixture:同样关闭 authorization,而且 org.a2aproject.sdk.transport.skipValidation=true,注释说明共享 Card 宣告了该部署未装入的 HTTP_JSON transport。路由测试不等于租户授权或 Card 全能力验证;本次也未阅读继承父类的所有断言或运行测试。^[raw/articles/a2a-jakarta-cross-node-state-and-effective-security-2026-09-13.md]

失败模式与最小接入验收

观察到的具体边界不能推出的结论建议隔离验证
B 订阅后固定 Thread.sleep(1000) 再驱动 A订阅已经就绪、早期事件必达用显式订阅就绪信号;断流/晚订阅后 getTask 对账
executor cancel()TaskNotCancelableErrortask API 存在就可取消工作验证不可取消响应,不自动重发有副作用任务
每节点独立 consumer group生产任意分区/分组布局都广播正确对比共享组、独立组、重启/重复事件
JPA push-config store 已装入实际 push 已开启或 webhook 安全单独核 Card、push enablement、目的地策略及回调回执
demo 关闭授权、gRPC 使用 plaintext企业多租户隔离或 TLS 已满足加真实 provider/TLS,测试 A 身份读取/续写 B 的任务

对 Hermes / llm-wiki 的可执行启发

  • 在接入记录分开保存 SDK 默认值 / 示例 override / 测试 fixture / 实际部署配置,不能只抄 README 安全卖点。
  • 任务结果区分「可查历史」「能订阅后续事件」「可恢复执行」「业务只执行一次」;用 Agent-Benchmarks 为每项单独设计断言。
  • 沿用 a2a-tck-conformance-coverage-and-security-boundaries:记录跳过的校验及其原因,不将测试类名称、声明 transport 或示例 expected output 当运行通过。

本轮验证与未执行项

本机解析固定 tag 文件并完成 12 项静态断言,核对 POM、关闭授权、广播分组、demo init、取消拒绝、订阅 sleep、streaming Card、fixture 和 README/POM 差异。结果在 raw/notes/ai-knowledge-radar-2026-09-13.md没有编译/启动 Java、Kafka/PostgreSQL,没有跑 TCK、task E2E、鉴权/崩溃恢复测试。 原文示例输出不作为本机结果。

写入记录

  • 2026-09-13 09:14 CST:新增固定 tag 双节点机制分析,核对 12 项静态配置/源码事实;显式区分 SDK 默认、demo override、fixture 和真实部署,保留 README 版本分歧及未验证恢复边界。