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

Node.js中ESOCKETTIMEDOUT的复现方法及异常处理问询

如何复现ESOCKETTIMEDOUT并处理该错误避免服务器崩溃

一、复现ESOCKETTIMEDOUT的简单方法

ESOCKETTIMEDOUT是读取超时:连接已成功建立,但客户端在指定时间内未收到服务器发送的后续响应数据。你之前的思路是对的,但需要配合客户端的超时配置才能触发这个错误,具体步骤如下:

1. 搭建挂起响应的测试服务器

用Express写一个接口,发送部分响应后故意挂起,不结束请求:

const express = require('express');
const app = express();
const port = 3000;

// 这个接口会发送部分数据后挂起连接
app.get('/hang-response', (req, res) => {
  // 发送一段部分响应
  res.write('This is a partial response...');
  // 不调用res.end(),让连接保持打开但不再发送任何数据
});

app.listen(port, () => {
  console.log(`Test server running on http://localhost:${port}`);
});
2. 客户端设置读取超时触发错误

使用request库发送请求时,明确设置readTimeout(读取超时时间),确保这个时间小于服务器挂起的时长:

const request = require('request');

request({
  url: 'http://localhost:3000/hang-response',
  readTimeout: 3000,  // 3秒内没收到后续数据就触发读取超时
  connectTimeout: 1000 // 连接超时时间(用于区分ETIMEDOUT)
}, (err, res, body) => {
  if (err) {
    console.error('Error code:', err.code); // 这里会输出ESOCKETTIMEDOUT
    console.error('Error details:', err);
    return;
  }
  console.log('Full response received:', body);
});

运行客户端代码后,3秒内服务器没有发送更多数据,就会触发ESOCKETTIMEDOUT错误。


二、处理ESOCKETTIMEDOUT错误,避免服务器崩溃

要防止这类错误导致服务器崩溃,核心是主动捕获错误,配合全局兜底机制,具体方案如下:

1. 每个请求单独捕获错误

最基础也最关键的是,在每个request调用的回调或Promise中处理错误:

// 回调方式
request({/* 配置 */}, (err, res, body) => {
  if (err) {
    if (err.code === 'ESOCKETTIMEDOUT') {
      // 针对读取超时的特殊处理:比如重试、返回友好提示
      console.warn('Request timed out while reading response, retrying...');
      // 这里可以加入重试逻辑
    } else {
      // 处理其他错误
      console.error('Request failed:', err);
    }
    return;
  }
  // 正常处理响应
});

// 如果使用request-promise(Promise风格)
const rp = require('request-promise');
async function makeRequest() {
  try {
    const body = await rp({/* 配置 */});
    // 正常处理
  } catch (err) {
    if (err.code === 'ESOCKETTIMEDOUT') {
      // 处理读取超时
    }
    console.error('Request error:', err);
  }
}
2. 全局兜底捕获未处理异常

作为最后一道防线,捕获全局层面的未处理错误,避免服务器直接崩溃:

// 捕获未处理的Promise拒绝(针对Promise风格的请求)
process.on('unhandledRejection', (reason, promise) => {
  console.error('Unhandled Rejection at:', promise, 'Reason:', reason);
  // 这里可以做一些清理工作,比如关闭数据库连接
});

// 捕获未捕获的同步/异步异常
process.on('uncaughtException', (err) => {
  console.error('Uncaught Exception:', err);
  // 不建议直接忽略,最好优雅退出后重启(比如用PM2自动重启)
  setTimeout(() => process.exit(1), 1000);
});
3. 优化请求与服务器配置
  • 合理设置超时参数:根据业务场景调整readTimeout和connectTimeout,避免过短导致误触发,或过长占用资源。
  • 添加重试机制:使用request-retry等库,对ESOCKETTIMEDOUT这类临时错误进行自动重试。
  • 服务器端超时控制:在Express中使用中间件(如express-timeout-handler),防止请求长时间挂起占用连接资源。

内容的提问来源于stack exchange,提问作者Gautam Kumar Samal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 09:52:32