← 中文资源

简体中文版本

调试 HTTP/2 流重置与神秘失败请求

用 nghttp 复现间歇性 RST_STREAM 错误,读取错误码并修复静默重置流的成帧问题或中间代理配置。

阅读英文原文

目标

HTTP/2 在一条连接上复用多个流,任何一方都能在不影响其他流的情况下重置其中一条。客户端把这表现为含糊的网络错误,但链路上携带的是明确的错误码。nghttp 会打印每个成帧事件,失败从间歇性噪声变成一个有编号、有文档的故障,可归因于源站或中间设备。

步骤要点

  1. 用 nghttp -v 访问失败端点并过滤 rst_stream/goaway/error,记录流 id 与错误码(如 stream=5 error_code=2 INTERNAL_ERROR)。
  2. 带 host 头直连源站复测:直连从不重置则中间设备是重置方,源站洗清嫌疑。
  3. 在 trace 里检查 content-length 与 end_stream:声明的长度大于实际发送且无 end_stream,与中间设备检测到成帧漂移后的 CANCEL(错误码 8)吻合。
  4. 用 –http1.1 走同一路径对比,全部成功则确认缺陷是 HTTP/2 特有的成帧问题而非业务逻辑。
  5. 修复后跑 50 次循环请求断言零失败,把这个循环留作回归检查。

排错提示

大上传报 PROTOCOL_ERROR(码 1)多是中间设备处理 CONTINUATION 帧或窗口尺寸有缺陷,先升级或临时限制请求体大小;只在并发时失败说明对端 SETTINGS_MAX_CONCURRENT_STREAMS 偏低并在重置超额流,应让客户端连接池遵守通告值;GOAWAY 紧接着出现是服务器优雅重启在排水,客户端应在 GOAWAY 后重连并只重放未完成的请求。

适用边界

错误码本身较粗,区分成帧缺陷与中间盒缺陷仍需“直连对比代理”实验;部分客户端把重置包装成通用网络错误,先别信 SDK 消息,用 nghttp 复现为准。

代码示例

nghttp -v https://api.example.com/v2/checkout 2>&1 \
  | grep -iE "rst_stream|goaway|error"

# prints e.g.
# [RST_STREAM stream=5 error_code=2 (INTERNAL_ERROR)]