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

NodeJS Express API超时问题求助(EC2与本地环境)

Express高并发大请求超时问题解决

问题场景

本地及EC2上部署的Express后端API,处理少量数据时运行正常,但发送500个单请求大小1MB的并发POST请求时,约2分钟后出现超时,服务器主动关闭Socket。尝试在/calculate接口首行添加res.socket.setTimeout(0);未生效。

错误信息

EC2服务器端错误

BadRequestError: request aborted
    at IncomingMessage.onAborted (/home/ec2-user/project/node_modules/raw-body/index.js:245:10)
    at IncomingMessage.emit (node:events:519:28)
    at IncomingMessage._destroy (node:_http_incoming:224:10)
    at _destroy (node:internal/streams/destroy:121:10)
    at IncomingMessage.destroy (node:internal/streams/destroy:83:5)
    at abortIncoming (node:_http_server:797:9)
    at socketOnClose (node:_http_server:791:3)
    at Socket.emit (node:events:531:35)
    at TCP.<anonymous> (node:net:338:12)

本地客户端错误

node:internal/deps/undici/undici:11730
    Error.captureStackTrace(err, this);
          ^

TypeError: fetch failed
    at Object.fetch (node:internal/deps/undici/undici:11730:11)
    at async Promise.all (index 9)
    at async D:\project\backend.js:49:32 {
  cause: SocketError: other side closed
      at Socket.onSocketEnd (node:internal/deps/undici/undici:8280:26)
      at Socket.emit (node:events:526:35)
      at endReadableNT (node:internal/streams/readable:1589:12)
      at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
    code: 'UND_ERR_SOCKET',
    socket: {
      localAddress: '192.168.100.2',
      localPort: 62485,
      remotePort: 3000,
      remoteFamily: 'IPv4',
      timeout: undefined,
      bytesWritten: 2300660,
      bytesRead: 277
    }
  }
}

依赖与环境

  • Node版本:v20.14.0
  • 依赖版本:
"dependencies": {
    "body-parser": "^1.20.2",
    "cors": "^2.8.5",
    "express": "^4.19.2"
}

解决方法

1. 修改Express服务器全局超时设置

Express 4.x中,app.listen()返回的是Node原生http.Server实例,直接设置该实例的超时属性即可覆盖默认的2分钟超时规则。

修改后的API代码:

const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');

const app = express();
app.use(cors());
app.use(bodyParser.json({limit: '30mb'}))
app.use(bodyParser.urlencoded({ limit: '30mb', extended: true }));

app.post('/calculate', async (req, res) => {
    // 原有业务代码
});

// 获取server实例并设置超时(0表示禁用超时,也可设置具体毫秒值如1800000表示30分钟)
const server = app.listen(3000, () => {
    console.log(`App listening on port 3000`);
});
server.setTimeout(0);

2. 为什么res.socket.setTimeout(0)无效?

请求在到达路由处理函数之前,可能已经在body-parser解析请求体的阶段触发了超时。全局设置服务器超时会覆盖所有请求的超时规则,包括请求体解析阶段,因此更有效。

3. 额外优化建议

  • 控制并发数:一次性发送500个并发请求可能超出服务器默认连接上限,可将请求拆分成小批次发送(比如每次50个),避免连接耗尽。
  • 调整连接参数:服务器侧可设置server.maxConnections提升最大连接数;客户端侧调整Node全局Agent的最大socket数:
    // 客户端代码中添加
    const http = require('http');
    http.globalAgent.maxSockets = 100;
    
  • 客户端超时控制:在fetch请求中添加主动超时逻辑,避免客户端无限制等待:
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), 300000); // 设置5分钟超时
    
    batchRequests.push(fetch('ip/calculate', {
        method: 'POST',
        body: JSON.stringify({file}),
        headers: { 'Content-Type': 'application/json' },
        signal: controller.signal
    }).finally(() => clearTimeout(timeoutId)));
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 07:23:19