A2A vs HTTP:Agent 协议性能压测的指标口径陷阱

A2A vs HTTP:Agent 协议性能压测的指标口径陷阱

导读:本文对比同一套 Agent 服务走 A2A 协议通道与 HTTP 会话通道两种接入方式的阶梯压测结果,核心教训是"跨协议对比之前必须先对齐指标口径":A2A 的 TTFT 指 task 帧到达(P50 约 1~2s,仅为服务端受理信号),HTTP 的 TTFT 指"首字"到达(P50 约 4~8s),两者直接比数字会得出"HTTP 慢三四倍"的假结论;真正可比的是完整时延,实测同阶梯下 HTTP 路径中位系统性快约 6s(约 -30%~-40%),且断连需区分 client 主动断与超时断,帧间隔要说明是相邻哪类帧。适合做跨协议/跨通道性能对比、对外交性能报告的测试与性能工程师。

分类:性能测试 | 标签:A2A、协议对比、压测、性能测试

为什么要对比两种通道

年底给「品牌 Agent 性能报告」交数据时,绕不开一个问题:同一套 Agent 服务,对外存在两种不一样的接入方式——A2A 通道和 HTTP 会话通道。

A2A 通道:遵循 Google 开源的 Agent2Agent 协议(公开协议,名称可保留),由测试环境内网的编排层暴露 POST /api/v1/a2a 入口,SSE 流式返回,帧语义为 task → artifact-update* → status-update final=true。

HTTP 会话通道:传统的"会话 Cookie"风格网关,先 POST /api/sessions 建会话,再 POST /api/sessions/{id}/messages 用 SSE 增量返回文本,鉴权走真实用户会话 Cookie。

业务侧其实不关心协议先进不先进,只关心一件事:用户走哪条通道体验更稳、能扛多少并发。所以我们用同一套问题词表、同一个并发阶梯(5 / 10 / 15 / 20 并发 × 5 轮,每路 250 样本),对两条通道分别跑了一轮阶梯压测,中间还验证了一个很容易踩的坑:

跨协议对比之前,指标口径到底对齐了没有?

先交代两路的差异背景(这也是"结果不能直接比"的一半原因):

  • A2A 一路:公网网关的沙箱鉴权凭据当时尚未接入正式授权体系,公网入口仍返回 401,最终回退到测试环境内网编排入口;每请求独立用户 ID + 新 contextId(即每请求新会话)。
  • HTTP 一路:走公网网关,每请求新建会话;鉴权用真实用户会话 Cookie(Cookie 会过期,复测前需刷新)。
  • 两路都是客户端计时,均未计入 OAuth 授权耗时、事件回调与 H5 渲染;问题词表两路同源。

核心:跨协议对比必须先对齐指标口径

两条通道的帧 / 流语义完全不同

先说清楚两条通道在"一个对话回合"里各自是怎么流式返回的。

A2A 通道(SSE 帧语义,公开协议约定):

task             —— 编排层确认受理任务(服务端已收到请求、开始调度)
artifact-update* —— 内容产物增量(一问多答/工具调用会多次出现)
status-update    —— final=true,流结束

HTTP 会话通道:

建会话 POST /api/sessions → 返回 session 标识
发消息 POST /api/sessions/{id}/messages → SSE 流
首个带 content 的增量("首字")→ 内容增量* → 流结束(有文本)

两条通道表面上都是 "发请求 → SSE → 结束",但每种事件到达的时点含义完全不同。如果不看协议语义直接拿数字比,就掉进陷阱了。

TTFT:A2A 的 "task 帧" ≠ HTTP 的 "首字"

这是本次最核心的一条经验:

指标 A2A 通道 HTTP 会话通道
TTFT 发请求 → 首个 kind=task 帧 发消息 → 首个带 content 的 SSE 增量("首字")
完整时延 发请求 → final=true 发消息 → SSE 流结束且有文本
E2E 不含独立建会话(无此环节) 含建会话(/api/sessions)

task 帧只是服务端确认受理、开始调度的信号;而 "首字"是模型真正吐出第一个文本片段的时刻。一次对话里,task 帧远早于首个 content——两者时间差动辄数秒。

所以实测中看到:

  • HTTP 首字 TTFT P50 约 4~8s;
  • A2A task TTFT P50 只有 1~2s。

如果不懂口径,会得出"HTTP 慢三四倍"的结论;但这是指标定义不同造成的系统差值,不是性能差距。这类对比要么把两路统一到同一个口径(例如都报"首事件/首文本"),要么各自注明帧语义再交表,绝不能把两列数字放进同一张表里当同一个指标用。

完整时延倒是可以比的——它近似"对话回合从开始到结束"的总耗时,两路语义都是"流真正结束"。本次对照也主要依赖这一列。

断连也要分类:client 主动断 vs 超时断

SSE 压测里"断连"不能只数一个总数,至少要分成两类:

  • client 主动断:客户端主动关闭连接(例如拿到答案后中止、或客户端自身超时设置)。
  • 超时断:服务端超过约定阈值(如 30s)未产出任何帧,客户端判定超时。
  • 另有两类服务端异常断:未发终帧(final)就关连接、进程崩溃 / TCP 层断开。

评判口径要跟线上监控一致:成功 = HTTP 200 + final=true + state=completed + 至少一段 message 文本;空答 / 流失败 / 异常断连分别计数。本次两路 250/250 全部 success,0 空答、0 流失败、0 断连——但表格里仍然要保留"断连率"这一行,否则读者无法判断成功率是怎么算出来的。

一句话口径表

项 HTTP 会话通道 A2A 通道
入口 公网网关 /api/sessions + /messages 内网编排 /api/v1/a2a
鉴权 真实用户 Cookie 每请求独立用户 ID
会话 每请求新建 session 每请求新 contextId
TTFT 发消息 → 首个带 content 的增量(首字) 发请求 → 首个 kind=task
完整时延 发消息 → SSE 流结束且有文本 发请求 → final=true
E2E 含建会话 不含(A2A 无独立建会话)

结论:TTFT 两路不可直接比数字(task 帧远早于首字 content);完整时延可比"对话回合耗时"量级。

压测设计与数据(脱敏示意)

设计要点:同一问题词表;阶梯 5/10/15/20 并发 × 5 轮;客户端计时;每请求新会话。以下数值保留原始数量级,已做脱敏示意,不代表任何真实业务数据。

A2A 通道(内网编排入口)

并发 N 成功率 断连率 完整 P50 完整 P95 完整 P99 TTFT(task) P50 TTFT P99 帧间隔 P50 帧间隔 P99 吞吐 rps
5 25 100% 0% 14.2s 18.1s 18.9s 1.03s 1.63s 1.5ms 90ms 0.34
10 50 100% 0% 16.4s 22.9s 25.8s 1.37s 3.13s 5.5ms 144ms 0.54
15 75 100% 0% 20.9s 32.3s 34.7s 1.73s 6.77s 7.9ms 156ms 0.65
20 100 100% 0% 22.6s 39.8s 44.5s 1.88s 4.73s 8.7ms 145ms 0.76

对照品牌 Agent 报告的模板门槛:

模板指标 门槛 本轮 结论
TTFT P50 ≤ 1s · P99 ≤ 3s 5 并发 P50=1.03s 贴线;≥10 并发 P50 1.37~1.88s、P99 3.13~6.77s 部分超线 高并发未达字面门槛
成功率 ≥ 99% 四档 100% 达标
完整响应 P50 ≤ 5s · P99 ≤ 15s P50 14~23s,P99 19~45s 未达字面门槛(Agent+LLM 长链路)
帧间隔 P50 ≤ 100ms 1.5~8.7ms 达标
断连 < 1% 0% 达标
并发承载 退化可控 5→20 完整 P50 14.2→22.6s(+59%),成功率不降 延迟抬升明显,错误率无退化

HTTP 会话通道(公网网关)

并发 N 成功率 建会话 P50 TTFT(首字) P50 TTFT P99 完整 P50 完整 P95 完整 P99 E2E P50 帧间隔 P50 吞吐 rps
5 25 100% 181ms 4.0s 8.9s 7.9s 11.6s 25.6s 8.0s 1.3ms 0.51
10 50 100% 237ms 5.3s 11.7s 10.6s 15.7s 18.6s 10.8s 4.1ms 0.81
15 75 100% 245ms 7.9s 15.0s 14.9s 22.3s 24.2s 15.1s 6.8ms 0.90
20 100 100% 334ms 7.6s 13.9s 16.6s 24.2s 30.7s 16.9s 3.4ms 1.01

全部样本 success(0 空答 / 0 失败 / 0 超时)。

跨通道对比(只比完整时延,不比 TTFT)

并发 HTTP 完整 P50 A2A 完整 P50 差值 HTTP TTFT(首字) P50 A2A TTFT(task) P50
5 7.9s 14.2s −6.3s(HTTP 更快) 4.0s 1.03s
10 10.6s 16.4s −5.8s 5.3s 1.37s
15 14.9s 20.9s −6.0s 7.9s 1.73s
20 16.6s 22.6s −6.0s 7.6s 1.88s

解读:

  • 稳定性:HTTP 会话通道在 20 并发下仍 0 失败,与 A2A 一致,两路成功率均为 100%。
  • 完整时延:同环境同阶梯下,HTTP 公网路径中位完整时延系统性优于 A2A 约 6s(约 −30%~−40%)。可能因素:链路差异(网关直连会话 vs A2A 翻译层)、词表命中/模型负载波动、首字后的吐字节奏不同。
  • TTFT:HTTP 首字(4~8s)明显高于 A2A task(1~2s),符合口径差异;若要对外对齐,HTTP 侧应另报"首事件/首 thinking",或共用 A2A kind=task 口径交表。
  • 建会话:P50 约 180~330ms,相对完整时延占比很小;E2E 与"仅消息"相差 0.1~0.3s。
  • 舒适区:HTTP 路径 5~10 并发体验更稳;15~20 并发完整 P50 抬到 15~17s,但仍无错误率退化。

OAuth / 授权环节在总耗时中的位置

对话压测本身不包含鉴权,但"总耗时"里其实有鉴权的位置:实际产品链路是 OAuth 授权 → 建会话 → 对话流。为了搞清楚这一环占多少,我们对授权接口单独跑了一轮小规模压测(auth_code → access_token,测试环境 mock 链路,非正式授权服务;1/5/10/20 并发 × 20 轮,共 720 次)。数值已脱敏示意:

并发 N 成功率 token P50 token P99 token 最大 issue+token P50
1 20 100% 18.7ms 69ms 72ms 99.6ms
5 100 100% 17.4ms 54ms 55ms 97ms
10 200 100% 22.5ms 80ms 82ms 114ms
20 400 100% 24.3ms 108ms 115ms 118ms

三点结论:

  1. 授权环节本身是毫秒级:token 接口 P50 约 17~24ms,P99 ≤ 108ms,相对秒级的对话完整时延占比很小;对照模板"授权时间 P50 ≤ 1s / P99 ≤ 3s"轻松达标。做对话压测时,把鉴权耗时分出去单独测,比混在完整时延里更干净。
  2. 鉴权的"位置"决定 TTFT 可比性:如果 A2A 一侧用"每请求独立用户 ID"绕开了正式授权、HTTP 一侧却把真实 Cookie 的鉴权算进"首帧之前",两路的 TTFT 口径就又差了一层。要在报告里写明 TTFT 计时点是否含鉴权。
  3. mock 环境要注明:测试环境的 mock 授权接口不代表生产正式授权服务的耗时,交表时必须标注,避免误导。

结论与选型建议

口径铁律(本文最想传达的一条):

跨协议做性能对比,第一步永远是"对齐指标口径"。A2A 的 TTFT 是 task 帧到达时间,HTTP 的 TTFT 是"首字"到达时间,两者不可直接比;只有完整时延(回合总耗时)在同一量级上可比。断连要分 client 主动断 / 超时断,帧间隔要说明是相邻哪类帧的间隔。

本次可交表的:成功率、断连率、帧间隔(P50)、完整时延阶梯(HTTP 与 A2A 各一套)、授权单独链路数据。

需与模型服务商协商的:模板里的"完整响应 P50 ≤ 5s / P99 ≤ 15s"对 Agent + LLM 长链路不现实,本轮实测 P50 14~23s、P99 19~45s;高并发下 TTFT(P50 ≤ 1s / P99 ≤ 3s)也只适合承诺低并发档位,≥10 并发首帧排队明显抬升,不宜对外承诺。

选型建议:

  • 聊天类 / 公网终端用户场景:HTTP 会话通道更直接。它省掉协议翻译层,完整时延中位系统性快约 6s,且 5~10 并发舒适区体验稳定;建会话开销只有 200~300ms 量级,可忽略。
  • 多 Agent 互操作 / 协议标准化场景:A2A 的价值不在单次延迟而在互操作(公开协议、标准化帧语义),选它时应按协议语义约定新口径,而不是拿它跟自定义 HTTP 通道的"首字 TTFT"硬比。
  • 对外并发承诺:建议保守承诺 ≤10 并发;交表代表值建议用 5 并发档;20 并发在实测中无错误率退化,但延迟抬升明显(完整 P50 +59%)。

最后是两个后续观察项:公网网关的正式鉴权打通后,应再补一档"同链路(都在公网)下的 A2A vs HTTP"对照,排除链路位置差异;服务端加三时刻埋点(收到请求 / 首帧写出 / 终帧写出)后,客户端计时可以升级成服务端口径,误差可解释。