修复: HTTP/2 重试测试偶发失败(GOAWAY 后立即关闭触发 RST 竞态) - #13
Merged
Merged
Conversation
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 个包测试通过。
There was a problem hiding this comment.
🟢 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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Important
📝 变更描述 / 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
🔗 关联任务 / Related Issue
✅ 提交前检查项 / Checklist
Bug fix,我已提交或关联对应 Issue,且不会将设计取舍、预期不一致或理解偏差直接归类为 bug。📸 运行证明 / Proof of Work
修复前(develop 基线
1918ac7d6,不含任何分支改动)单用例重复 10 次出现 1 次失败;分支代码上循环复现,第 1 轮即失败:修复后目标用例组(4 个 HTTP/2 重试用例)连续 90/90 通过;
relay/channel整包连跑 4 次全绿;全量go test ./...33 个包全部通过。