如何测试代理链路中的 HTTP/2 GOAWAY 排空

一条 HTTP/2 连接可以同时承载许多请求。端点发送 GOAWAY 时,并不只是表示“套接字出错”,而是在声明连接即将退役,并给出可能已经处理到的流边界。客户端若忽略这一边界,可能继续把新任务放到即将关闭的连接上,造成请求丢失,甚至重复执行不可重放的写操作。
本指南用于验证经过代理的 HTTP/2 链路:收到 GOAWAY 后,旧连接不再接收新流;符合条件的在途流可以完成;新任务切到替代连接;只有语义和流证据都允许的请求才会自动重试。
正确理解 GOAWAY 证据
记录错误码、最后流标识、接收时间、连接标识以及每个流的状态。高于最后流标识的流可视为未被发送方处理;低于或等于该标识但尚未完成的流则存在歧义,因为部分数据可能已经交给上层应用。
不要把策略简化为“失败就全部重试”。读取请求可能符合自动重试策略;创建订单、启动任务或扣费的 POST 若没有响应,并不代表可以安全重放。即使使用幂等键,也要确认目标系统确实会强制去重。
搭建隔离测试环境
只使用自有或已获授权的目标与代理线路。测试源站至少提供:快速读取、延迟读取、带服务端幂等键的写入、不带重放保护的写入,以及可用于核对的请求和连接标识。
客户端需要输出连接 ID、流 ID、分配时间、请求头发送时间、响应状态、完成结果与重试决策。代理日志应移除凭据和可能包含个人信息的响应正文。
建立基线
通过代理打开一条 HTTP/2 连接,同时发送快速、延迟和写入请求。先确认这些请求确实复用同一连接,并确认源站只执行一次每个操作。
记录正常情况下的 p50、p95 完成时间,新连接建立时间和稳定并发量。没有基线,排空测试很容易把普通延迟误判为关闭异常。
触发优雅排空
先启动多个延迟流,再让受控端点发送带 NO_ERROR 的 GOAWAY。在最后流标识以内保留部分在途流,并在帧到达后立即尝试安排新任务。
合格行为应包括:
- 旧连接立即进入 draining 状态;
- 不再向旧连接分配新流;
- 符合条件的在途流在限定窗口内完成;
- 新任务使用替代连接;
- 明确未处理的流进入对应重试分类;
- 有歧义的非幂等操作进入核对流程,而不是盲目重放。
随后降低最后流标识,使若干刚创建的流落在边界之外;再测试错误型 GOAWAY,以及发送帧后立即断开连接的场景。客户端不能假定每次排空都能正常结束。
覆盖危险时序
加入受控抖动并多次运行以下情况:GOAWAY 在请求头发送前到达、在请求头后但请求体未完成时到达、在响应体流式传输期间到达、连续两个 GOAWAY 且第二个边界更低、排空截止前连接断开、替代连接的认证或 TLS 校验失败,以及大量工作线程同时观察到 GOAWAY。
确认并发不会放大成重试风暴。同一路由或连接池只应产生受控的替代连接尝试。重试上限可参考代理重试预算指南,连接寿命边界可结合代理空闲超时与 Keep-Alive 测试验证。
预先定义重试分类
请求类型 | 流证据 | 自动动作
幂等读取 | 明确未处理 | 在预算内重试
幂等读取 | 状态有歧义 | 仅按已记录策略重试
受保护写入 | 明确未处理 | 使用同一强制幂等键重试
受保护写入 | 状态有歧义 | 先按幂等键核对
无保护写入 | 存在任何歧义 | 不自动重放
传输层重试、应用重试和业务核对必须分开。库的默认行为不能替代业务安全策略。
关键验收指标
- GOAWAY 后分配到旧连接的新流数量必须为零;
- 符合条件的在途流完成率;
- 替代连接建立时间;
- 按请求类型和原因统计的重试量;
- 重复副作用必须为零;
- 孤立或无人跟踪的操作数量;
- 每个原始请求造成的重试放大倍数;
- 排空时长和强制关闭次数;
- 未受影响连接与路由的成功率。
按代理协议、出口市场、客户端运行时、库版本、IPv4/IPv6、粘性或轮换会话分组。轮换线路在新连接上更换出口可能符合预期;粘性会话则可能需要新的会话令牌或明确的连续性校验。
上线检查清单
- GOAWAY 有独立事件类型,不会被合并为普通连接错误。
- 脱敏日志包含连接与流标识。
- 排空连接不再接收新流。
- 在途请求有明确且有限的完成窗口。
- 替代连接创建会合并并限速。
- 重试依据请求语义、流证据和幂等控制。
- 不安全或有歧义的写入进入业务核对。
- 重复故障注入下仍无重复副作用。
- 重试放大保持在预算内。
- IPv4、IPv6 和目标市场分别测试。
- 凭据不会进入跟踪数据或测试夹具。
- 回滚可以关闭自动重放,而不必停止全部流量。
常见问题
GOAWAY 一定表示错误吗?
不一定。NO_ERROR 常用于优雅退役,其他错误码可能表示协议或内部故障。无论哪种情况,边界生效后旧连接都不应再接收新流。
所有高于最后流标识的请求都能重试吗?
传输证据表明发送 GOAWAY 的对端没有处理这些流,但仍需遵守业务截止时间、认证、幂等键和重试预算。
新连接是否要等旧连接完全关闭后再建立?
通常不需要。新任务应转到替代连接,同时允许旧流在限定时间内完成;但要限制替代连接并发,避免全局排空引发连接风暴。
代理上游若使用 HTTP/1.1 怎么办?
分别验证两端可观察行为。客户端一侧的 GOAWAY 边界仍然有效,而有歧义的写入是否已执行,需要依赖源站证据判断。
合规说明
仅在已获授权的系统、账号、代理线路和数据范围内执行排空与重试测试。遵守目标条款、速率限制和隐私要求;使用合成记录、隐藏凭据,并只保留可靠性与审计所需的证据。
来源说明:IETF,RFC 9113《HTTP/2》,2022 年 6 月。外部研究地址仅保存在内部运营记录中。