Skip to content

修复: HTTP/2 重试测试偶发失败(GOAWAY 后立即关闭触发 RST 竞态) - #13

Merged
LoSealL merged 1 commit into
developfrom
fix/http2-goaway-test-flaky
Sep 8, 2026
Merged

LoSealL merged 1 commit into
developfrom
fix/http2-goaway-test-flaky

Conversation

@LoSealL

@LoSealL LoSealL commented Sep 8, 2026

Copy link
Copy Markdown

⚠️ 提交说明 / PR Notice

Important

  • 请提供人工撰写的简洁摘要,避免直接粘贴未经整理的 AI 输出。

声明: 本 PR 的代码与描述由 AI 生成/辅助完成(当前提交者非仓库历史核心开发者)。

📝 变更描述 / Description

修复 TestUpstreamGetBody_HTTP2RetryAfterGracefulGoAway_PassThrough 等用例的偶发失败(复现失败率约 10–20%),仅改动测试文件,不涉及任何生产代码。

失败报错为 wsarecv: An existing connection was forcibly closed by the remote host(TCP RST)。根因在测试服务器(手写原始 HTTP/2 帧服务器):写完 GOAWAY / 响应帧后立即 conn.Close(),而连接中往往还有客户端已发出、服务器未读的入站帧(SETTINGS ACK、WINDOW_UPDATE 等)。Windows 上关闭仍有未读数据的 socket 会发送 RST 而非 FIN;该 RST 与客户端读取 GOAWAY 帧竞速——抢先到达时客户端只看到连接级错误,transport 不再在新连接上重试,client.Do 直接返回错误。

修复方式是补齐真实服务器的优雅关闭语义(RFC 9113 §6.8):新增 drainH2TestConnection,写完末帧后由后台 goroutine 持续读取并丢弃帧直到对端关闭(受既有 15s 连接 deadline 约束)再关闭 socket,从机制上消除 RST。GOAWAY 服务器(第一条连接交给排水 goroutine 后主循环立即 accept 重试连接,不阻塞重试路径)与 RST_STREAM 服务器(另两个重试用例共用,同样存在该缺陷)的所有正常关闭路径统一改为排水后关闭;错误路径保持立即关闭(此时客户端已注定失败)。

🚀 变更类型 / Type of change

  • 🐛 Bug 修复 (Bug fix) - 请关联对应 Issue,避免将设计取舍、理解偏差或预期不一致直接归类为 bug
  • ✨ 新功能 (New feature) - 重大特性建议先通过 Issue 沟通
  • ⚡ 性能优化 / 重构 (Refactor)
  • 📝 文档更新 (Documentation)

🔗 关联任务 / Related Issue

✅ 提交前检查项 / Checklist

  • 人工确认: 我已亲自整理并撰写此描述,没有直接粘贴未经处理的 AI 输出。
  • 非重复提交: 我已搜索现有的 Issues 与 PRs,确认不是重复提交。
  • Bug fix 说明: 若此 PR 标记为 Bug fix,我已提交或关联对应 Issue,且不会将设计取舍、预期不一致或理解偏差直接归类为 bug。
  • 变更理解: 我已理解这些更改的工作原理及可能影响。
  • 范围聚焦: 本 PR 未包含任何与当前任务无关的代码改动。
  • 本地验证: 已在本地运行并通过测试或手动验证,维护者可以据此复核结果。
  • 安全合规: 代码中无敏感凭据,且符合项目代码规范。

📸 运行证明 / Proof of Work

修复前(develop 基线 1918ac7d6,不含任何分支改动)单用例重复 10 次出现 1 次失败;分支代码上循环复现,第 1 轮即失败:

Error: Received unexpected error:
    Post "http://upstream.test/v1/chat/completions": read tcp 127.0.0.1:5280->127.0.0.1:5278:
    wsarecv: An existing connection was forcibly closed by the remote host.
Messages: the transport must retry on a new connection after graceful GOAWAY

修复后目标用例组(4 个 HTTP/2 重试用例)连续 90/90 通过;relay/channel 整包连跑 4 次全绿;全量 go test ./... 33 个包全部通过。

TestUpstreamGetBody_HTTP2RetryAfterGracefulGoAway_PassThrough 等用例
偶发失败,报错为 wsarecv: connection forcibly closed(TCP RST)。

根因:测试服务器写完 GOAWAY/响应帧后立即 conn.Close(),此时连接中
仍有客户端未读的入站帧(SETTINGS ACK、WINDOW_UPDATE 等)。Windows
上关闭仍有未读数据的 socket 会发送 RST 而非 FIN;RST 与客户端读取
GOAWAY 帧竞速,抢先到达时连接级错误取代了优雅关闭,transport 不再
重试,client.Do 直接报错。

修复:模拟真实服务器的优雅关闭(RFC 9113 §6.8)——新增
drainH2TestConnection,写完末帧后由后台 goroutine 持续读取并丢弃
帧直到对端关闭(受既有 15s 连接 deadline 约束)再关闭 socket,
彻底消除 RST。GOAWAY 服务器与 RST_STREAM 服务器两个辅助函数的
所有关闭路径统一改为排水后关闭;错误路径仍立即关闭。

验证:目标用例 90/90 连续通过(修复前约 10–20% 失败率),整个
relay/channel 包及全量 33 个包测试通过。
Copilot AI lite review requested due to automatic review settings September 8, 2026 14:50

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

变更范围仅限测试代码且逻辑自洽,通过连接排水消除了可复现的关闭竞态来源,未发现需要进一步修改的代码问题。

Pull request overview

本 PR 聚焦修复 relay/channel/api_request_getbody_test.go 中 HTTP/2 重试相关用例的偶发失败(GOAWAY/RST 竞态导致 Windows 上出现 wsarecv 连接被强制关闭),通过让测试用的“手写 HTTP/2 帧服务器”在发送末帧后执行更接近真实服务器的优雅关闭(排水/drain)来消除 TCP RST 的非预期影响。改动仅涉及测试代码,不触及生产逻辑。

Changes:

  • 新增 drainH2TestConnection:在发送 GOAWAY/响应后后台持续读取并丢弃入站帧,直到对端关闭或连接 deadline 触发,再关闭 socket。
  • runResetOnFirstStreamServer 的正常关闭路径改为 drain 后关闭,避免未读入站帧导致 RST。
  • runGoAwayAfterFirstRequestServer 的 GOAWAY 与最终响应关闭路径改为 drain 后关闭,并确保 GOAWAY 后立即 accept 重试连接不被阻塞。
File summaries
File Description
relay/channel/api_request_getbody_test.go 为 HTTP/2 测试服务器补齐连接排水逻辑,避免 GOAWAY/响应后立即 Close 引发 RST 竞态导致测试 flaky
Review details
  • Files reviewed: 1/1 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@LoSealL
LoSealL merged commit 5141f6b into develop Sep 8, 2026
4 checks passed
@LoSealL
LoSealL deleted the fix/http2-goaway-test-flaky branch September 8, 2026 14:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants