DEBUG.WIKI
V.PS:让项目靠近用户,亚太、欧洲、北美 KVM VPS
IPPeak:从目标地区访问网页,住宅代理、SEO 监测、广告验证
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国

Node.js 第二次 HTTP 请求报 ECONNRESET,检查连接复用

第一次请求返回,下一次却报连接重置:检查核心HTTP模块的reusedSocket、空闲关闭和Agent,只有可安全重复的操作才做有界重试。

第一次 HTTP 请求已经完整返回,隔了一段时间再请求同一服务却报 read ECONNRESET 或 socket hang up。如果代码使用 node:http、node:https 和保留空闲连接的 Agent,需要检查第二次请求是否拿到了服务端正在关闭的旧连接。

这条处理路径适用于核心 HTTP 模块的 ClientRequest。内置 fetch() 使用的接口不同,不能把下面的 req.reusedSocket 直接套在 fetch 的响应对象上。第一次请求也没有建立连接,或者传输响应正文时才断开,则要按相应阶段另查。

先记录失败请求是否复用了连接

在现有请求的错误处理入口保留下面两项信息。req 指应用真正发出的请求对象,不要为了检查再创建一条业务请求:

req.on('error', (err) => {
  console.error({
    code: err.code,
    reusedSocket: req.reusedSocket,
  });
  // 接回应用原有的失败处理,不能只打印后继续当作成功。
});

reusedSocket 为真且错误是 ECONNRESET,说明这次失败值得沿连接池复用路径调查,并不能单凭两个字段确认根因。还应记录上一条响应结束、下一条请求发出和失败的时间,对齐服务端、代理及负载均衡的关闭记录。避免在日志里输出认证头、Cookie 和带凭据的完整地址。

服务端关闭空闲连接与客户端收到关闭通知之间存在时间窗口。客户端仍把 socket 留在空闲池里,此时发出新请求,就可能选中它。主线程长时间执行同步计算会延迟网络事件处理,让这种时间关系更难判断;在调用前随便加一个短延时,不能保证关闭通知已经处理完。

看实际 Agent,别只看 keepAliveMsecs

确认运行进程的 Node 版本、真正使用的 HTTP 或 HTTPS Agent,以及 keepAlive、scheduling、timeout 等设置。以 Node.js 24.10.0 为例,核心 http.globalAgent 启用了 keep-alive,采用 lifo 和 5000 毫秒 timeout;自行 new http.Agent() 时,keepAlive 默认却是 false。应用或 SDK 换过 Agent 后,不能继续拿全局值解释它。

keepAliveMsecs 是 TCP keep-alive 探测的初始等待时间,不是 HTTP 空闲 socket 留在池里的寿命。把它调短,不能直接保证服务端关闭前客户端已丢弃旧连接。

Node.js 24.7.0 增加的客户端 agentKeepAliveTimeoutBuffer,可在处理服务端 Keep-Alive: timeout=... 提示时提前留出窗口;实际效果还取决于 Agent 的 timeout、收到的提示和网络路径。Node.js 24.6.0 的服务端 keepAliveTimeoutBuffer 则在服务端内部多留一段时间,只影响新建立的连接。旧版本不能直接套用这些选项,它们也不能防止实例重启、代理主动关闭等所有断开。

对照时保持目标、方法、TLS、认证和代理条件一致。可以在受控环境对已确认只读的请求临时禁用复用,观察失败是否随之变化;如果有改善,也要结合关闭记录判断。每次重新建立 TCP 或 TLS 连接有成本,不宜把修改全局 Agent 当作所有请求的默认修复。

重试前,先确认这条操作可以重复

客户端报连接错误,不代表服务端没收到请求,更不代表远端没有完成写入。创建订单、扣费或提交任务等 POST,不能只因 reusedSocket 为真就再发一次;流式请求体也未必能重放。

对于已经确认可安全重复的读取,才考虑在“复用了连接且报 ECONNRESET”这一分支最多追加一次尝试。两次尝试应共享原有总截止时间,第二次失败明确返回应用的失败入口。不要递归无限重试,也不要把每次重试重新获得完整超时当成有界处理。响应需要按原流程消费、取消或释放,专用 Agent 也只能在所属请求全部结束后销毁。

有幂等键或结果查询机制的写入,应按该接口真正保证的语义核对远端状态,再决定是否重试。仅有 HTTP 方法名称、一次客户端错误或“第二次看起来没到服务端”的猜测,都不足以建立这个保证。

若时间线显示长时间同步工作紧挨着下一次请求,评估将计算分批执行或移到 Worker Threads;这项调整仍需核对业务顺序和共享数据。保留原 Agent 配置及重试入口,修复后观察相同负载、空闲间隔和服务端关闭条件,并检查业务结果。恢复配置可以撤回连接管理调整,无法撤销已发送的远端操作。

如果失败发生在首次连接阶段,错误包含 ETIMEDOUT、ENETUNREACH 和多个解析地址,可另查地址族连接尝试的等待时间,不要把它与这里的旧连接复用混在一起。