You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node 16.14.2环境下Socket hang-up error无法被try-catch捕获求助

Node.js 16.14.2 下 ECONNRESET 错误导致 Pod 退出的解决优化方案

生产环境使用 Node.js 16.14.2,Pod 偶发因 ECONNRESET(Socket hang-up 类错误)异常退出。已在代码中添加 try-catch 块,但无法捕获该类底层错误。相关代码及错误日志如下:

原代码示例

export const keepAlive = () => {  
  const keepAliveSettings = {    
    keepAlive: true,    
    maxSockets: config.MAX_SOCKETS,    
    maxFreeSockets: config.MAX_FREE_SOCKETS,    
    timeout: config.SOCKETS_KEEPALIVE,    
    keepAliveTimeout: config.SOCKETS_KEEPALIVE_TTL,  
  };  
  const httpAgent = new Agent(keepAliveAgentSettings);  
  
  // for SSL  
  keepAliveAgentSettings.rejectUnauthorized = false;  
  const httpsAgent = new Agent.HttpsAgent(keepAliveAgentSettings);  
  return {    
       httpsAgent,    
       httpAgent,  
  };
};

// Axios instance with AgentKeepAlive setup.
export const getAxiosInstance = () => {  
  const webAgent = keepAlive();  
  return axios.create({    
    httpAgent: webAgent.httpAgent,    
    httpsAgent: webAgent.httpsAgent,  
  });
};

// Inside the function
let response;
try {    
  response = await axiosInstance.get(`${url}${xt}${param}`, { httpsAgent: getHttpsAgent() });  
} catch (error) {
  console.log("error.message")
}

错误日志

Error: read ECONNRESET
at TCP.onStreamRead (node:internal/stream_base_commons:217:20)
at TCP.callbackTrampoline (node:internal/async_hooks:130:17) {
  errno: -104,
  code: 'ECONNRESET',
  syscall: 'read'
} [message]: undefined 

问题分析

ECONNRESET 是 TCP 层面的连接重置错误,通常由远端服务器主动断开连接或网络异常触发。现有代码存在几个关键问题导致错误无法被捕获:

  • Agent 配置引用污染:创建 httpAgent 后修改共享的 keepAliveSettings 对象,导致 httpAgent 意外继承了 rejectUnauthorized: false,引发潜在连接异常。
  • 请求重复指定 Agent:已通过 axios.create 配置全局 Agent,但请求时又传入新的 getHttpsAgent(),导致 Agent 实例冲突,错误处理链路断裂。
  • 底层 Socket 错误未被捕获:Agent 管理的 Socket 发生错误时,若未监听 error 事件,会直接抛出未捕获异常导致进程退出,无法被 Axios 的 try-catch 捕获。
  • 错误处理不完整:catch 块仅打印字符串 "error.message",未输出实际错误详情,无法定位问题。

优化方案及代码调整

1. 修复 Agent 配置引用问题

对配置对象进行浅拷贝,避免修改时污染其他 Agent 实例,并添加 Socket 错误监听:

import { Agent } from 'https';
import config from './your-config-path';

export const keepAlive = () => {  
  const baseSettings = {    
    keepAlive: true,    
    maxSockets: config.MAX_SOCKETS,    
    maxFreeSockets: config.MAX_FREE_SOCKETS,    
    timeout: config.SOCKETS_KEEPALIVE,    
    keepAliveTimeout: config.SOCKETS_KEEPALIVE_TTL,  
  };  

  // HTTP Agent 使用基础配置
  const httpAgent = new Agent({ ...baseSettings });  
  // HTTPS Agent 单独扩展配置
  const httpsAgent = new Agent.HttpsAgent({
    ...baseSettings,
    rejectUnauthorized: false
  });  

  // 监听 Agent 底层 Socket 错误,避免未捕获异常导致进程退出
  const handleAgentError = (err) => {
    console.error('Agent Socket 错误:', { code: err.code, message: err.message });
    // 可添加告警或资源清理逻辑
  };
  httpAgent.on('error', handleAgentError);
  httpsAgent.on('error', handleAgentError);

  return { httpsAgent, httpAgent };
};

2. 统一 Axios 实例的 Agent 使用

取消单个请求中重复指定 Agent 的操作,确保使用全局配置的实例:

import axios from 'axios';

export const getAxiosInstance = () => {  
  const webAgent = keepAlive();  
  return axios.create({    
    httpAgent: webAgent.httpAgent,    
    httpsAgent: webAgent.httpsAgent,
    timeout: config.REQUEST_TIMEOUT // 添加请求超时,避免无限等待
  });
};

3. 完善请求错误处理

确保 try-catch 捕获完整错误信息,并添加 Axios 拦截器处理全局错误:

const axiosInstance = getAxiosInstance();

// 响应拦截器统一处理 HTTP 错误
axiosInstance.interceptors.response.use(
  (response) => response,
  (error) => {
    console.error('Axios 请求错误:', {
      url: error.config?.url,
      code: error.code,
      message: error.message
    });
    return Promise.reject(error);
  }
);

// 业务请求代码
let response;
try {    
  response = await axiosInstance.get(`${url}${xt}${param}`);
} catch (error) {
  console.error('请求捕获错误:', error);
  // 添加重试逻辑或降级处理逻辑
}

4. 全局未捕获异常防护

在进程层面添加监听,防止未捕获的异常导致 Pod 直接退出:

// 监听未捕获的同步异常
process.on('uncaughtException', (err) => {
  console.error('未捕获异常:', err);
  // 执行优雅退出逻辑,比如清理资源后重启进程
  process.exit(1);
});

// 监听未处理的 Promise 拒绝
process.on('unhandledRejection', (reason, promise) => {
  console.error('未处理的 Promise 拒绝:', reason);
  promise.catch(err => console.error('Promise 拒绝详情:', err));
});

5. 调整 Socket 超时配置

确保 keepAliveTimeout 小于远端服务器的连接超时时间(例如服务器超时为 60s,可设置为 55s),避免服务器主动断开连接时触发 ECONNRESET。


内容的提问来源于stack exchange,提问作者user12551649

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 01:10:26