Playwright Keep-Alive 开放问题:防止代理 API 测试因套接字复用而重置

Microsoft Playwright 仓库在 2026 年 9 月 13 日出现一条新的开放 Issue。报告者称,APIRequestContext 在接近服务器声明的 Keep-Alive 超时边界复用 HTTP 套接字时,可能抛出 ECONNRESET。报告中的并发读取测试在约六秒边界复现了失败,而浏览器导航没有表现出同样症状;报告者认为 Chromium 对已复用套接字的失败进行了重试。
这仍是用户提交的开放问题,并非维护者已经确认的缺陷,也没有已发布修复。报告环境为 Playwright 1.58.2、Node 26.3.0、macOS arm64 和 Next.js 开发服务器。团队不能把所有连接重置都归因于它,但可以据此检查空闲边界、保存失败阶段,并确保代理环境下的重试不会制造重复副作用。
内部研究来源:Microsoft Playwright 仓库,Issue 42698,《APIRequestContext ignores the server's Keep-Alive timeout, producing ECONNRESET on socket reuse》,2026 年 9 月 13 日创建。
为什么代理会让归因更困难
代理请求可能同时存在多层可复用连接:客户端到 HTTP 代理的连接、CONNECT 隧道中的目标 TLS,以及目标服务器自己的 Keep-Alive 策略。SOCKS5 还会引入网关与 DNS 路径。
如果重置只被记成“代理错误”,就无法判断问题发生在客户端到网关、隧道、目标连接还是应用响应阶段。并发可能扩大时间竞争窗口,但不一定是根因。
使用自有测试夹具复现
使用你控制、会声明较短 Keep-Alive 超时的服务器,响应中返回随机挑战和服务端请求编号。直连与代理测试保持相同 Playwright、Node、请求内容与超时。
记录测试编号、路由别名、请求方法、幂等键哈希、连接序号、请求前空闲毫秒数、代理会话模式、响应挑战、服务端请求编号哈希、错误码、失败阶段与重试次数。不得保存代理密码、Cookie、授权头或原始幂等键。
在超时点前后密集取样。例如服务器约六秒关闭连接,可测试 4.5、5.0、5.5、5.9、6.0、6.1、6.5 和 7.0 秒。先用单工作线程,再使用受控小并发,每个区间重复数次。
分开直连、代理和浏览器对照
| 对照 | 目的 |
|---|---|
| 直连 APIRequestContext | 判断不经代理是否也发生重置 |
| 代理 APIRequestContext | 测量网关和隧道影响 |
| 浏览器导航 | 检查浏览器重试是否掩盖问题 |
| 新请求上下文 | 比较新连接池和复用套接字 |
| 关闭复用对照 | 验证避免复用是否改变症状 |
不要在混合浏览器与 API 的上下文中贸然全局设置 Connection: close,否则可能连正常的页面与静态资源复用也一起关闭。
只在操作安全时重试
Issue 报告者建议仅对 ECONNRESET 的幂等请求做重试,并刻意排除 POST,因为服务端可能已经创建成功,只是客户端读取响应时被重置。对采集、注册与账户流程,这一区别非常关键。
- 只读 GET 通常可在上限内重试;
- PUT、PATCH、DELETE 只有在服务端强制幂等且能查询结果时才安全;
- POST、下单、注册、发消息等默认不能盲目重放;
- 认证、权限与策略错误应立即停止。
即使方法名通常被视为幂等,也可能触发业务副作用,因此要在自有服务器验证实际行为。
使用结果账本
重试写操作前,保存经过哈希的操作标识并查询服务端结果。账本应区分未发送、已发送但未看到响应、服务端已接受、服务端拒绝、重复已阻止和最终结果未知。
结果未知时应进入对账流程,而不是直接重放。这样才能避免读取侧重置制造重复记录或订单。
单独验证代理会话
重试可能复用原代理连接、创建新隧道,或取得新的轮换出口,应明确记录。如果目标把状态绑定到来源 IP,即使 HTTP 方法本身安全,换出口也可能改变结果。
可使用住宅代理会话粘性测试验证路由身份,用代理连接池指南定义连接池边界,并让重试负载保持在代理并发饱和测试得出的安全容量内。
不要误判故障层
发生重置时,依次确认套接字是新建还是复用、空闲时间与服务器超时的关系、服务端是否收到并完成操作;随后分别直连、创建新请求上下文、比较浏览器与 API 行为,并在不改变目标的情况下更换网关。日志只保留必要的客户端和服务端时间点。
不要抓取第三方流量。如果确需更深层的数据包证据,应在获批实验环境中进行并最小化载荷留存。
上线检查清单
- 明确该信息是开放报告,不是正式修复说明;
- 已完成直连和代理的空闲边界测试;
- 可区分新套接字和复用套接字;
- 服务端接收记录能与客户端结果关联;
- 每类重试操作都有安全分类;
- 写操作重试具备幂等与对账;
- 重试次数和总耗时有上限;
- 已记录代理会话是否变化;
- 日志不包含凭据或个人数据;
- 已验证回退或连接池缓解方案。
常见问题
每个 ECONNRESET 都是这个问题吗?
不是。网关、目标、局域网、TLS 关闭和应用进程都可能重置连接。必须先复现空闲边界再归因。
所有重置都可以重试一次吗?
不可以。写操作可能已经成功,只有证明安全或具备服务端幂等与对账时才能重试。
为什么浏览器导航可能正常?
报告者称其测试中 Chromium 重试了复用套接字失败,而 APIRequestContext 暴露了错误。需要在自己的版本与环境中验证。
关闭 Keep-Alive 是永久修复吗?
它可以用于诊断或临时缓解,但会增加连接成本,广泛应用还可能影响浏览器资源加载。上线前要测量范围和代价。
合规说明
只在自有或明确获准的系统与代理路由上复现。遵守平台规则、合同、速率限制与隐私要求。没有明确幂等保护和结果对账时,不得自动重试付款、注册等有实际后果的操作。