Express.js(Node.js)中的ECONNRESET有多个请求

Tam*_*mas 5 javascript http node.js express econnreset

给定标准的Express.js设置

const express = require('express');
const app = express();
const router = express.Router();

router.get('/test/:id', (req, res) => {
  return res.status(200).json({ hello: 'world' });
});

app.use('/api', router);

app.listen(3000, () => console.info('Up on port 3000));
Run Code Online (Sandbox Code Playgroud)

我一次又一次地向端点发出1000个请求:

const fetch = require('node-fetch');
for (let i = 0; i < 1000; i++) {
  let id = Math.floor(Math.random() * 12) + 1;
  fetch(`http://localhost:3000/api/test/${id}`).then(res => res.json()).then(data => console.log(data)).catch(error => console.error(error));
}
Run Code Online (Sandbox Code Playgroud)

我确实经常看到返回的数据,但有时我会看到ECONNRESET错误。ECONNRESET错误消息的数量也各不相同:有时我会收到一些,有时会更多。我确实了解该消息,但是无法解决该问题背后的问题。

这是一个示例错误:

{ FetchError: request to http://localhost:3000/api/test/8 failed, reason: connect ECONNRESET 127.0.0.1:3000
    at ClientRequest.<anonymous> (node_modules/node-fetch/lib/index.js:1345:11)
    at ClientRequest.emit (events.js:182:13)
    at Socket.socketErrorListener (_http_client.js:399:9)
    at Socket.emit (events.js:182:13)
    at emitErrorNT (internal/streams/destroy.js:82:8)
    at emitErrorAndCloseNT (internal/streams/destroy.js:50:3)
    at process.internalTickCallback (internal/process/next_tick.js:72:19)
  message:
   'request to http://localhost:3000/api/departments/8 failed, reason: connect ECONNRESET 127.0.0.1:3000',
  type: 'system',
  errno: 'ECONNRESET',
  code: 'ECONNRESET' }
Run Code Online (Sandbox Code Playgroud)

请注意,我尝试使用axios发出请求,axos是内置的HTTP模块,可以使用。我确定问题出在我的Express应用程序处理该请求,但不确定如何正确解决它。

更新1:

根据评论中的建议,这是异步版本:

async function f() {
  const array = Array.from(Array(1000).keys());
  for (const el of array) {
    try {
      let id = Math.floor(Math.random() * 12) + 1;
      const result = await fetch(`http://localhost:3000/api/test/${id}`).then(res => res.json());
      console.log(result);
      return result;
    } catch(e) {
      console.log(e);
    }
  }
}

f();
Run Code Online (Sandbox Code Playgroud)

现在,我偶尔收到ECONNREFUSED消息。

更新2:

根据Mazki516的回答,以下是有效的解决方案:

// previous require statements
const cluster = require('cluster');
const os = require('os');

if (cluster.isMaster) {
  const cpuCount = os.cpus().length
  for (let i = 0; i < cpuCount; i++) {
      cluster.fork()
  }
} else {
  const app = express();
  // rest of the route definitions
  // also app.listen() etc...
}
cluster.on('exit', worker => {
  console.log(`${worker.id} removed`);
  cluster.fork();
});
Run Code Online (Sandbox Code Playgroud)

Maz*_*516 5

您看到这的原因之一是因为您以“并行”方式进行呼叫。您确实一个接一个地开始调用,但是循环可能在服务器返回第一个结果之前结束。循环一直持续到最后,使调用堆栈充满了对服务器的1000个异步请求。

您正在达到硬件/软件限制,并且代码没有错。如果您确实想构建可以同时处理1k(及更多)请求的服务器,那么我将研究一下node的“集群”模块。

请注意,在服务器之间进行网络作业时,可以使用并发限制。(例如:同时最多4个请求)

但是您始终可以将服务器扩展到一台机器之外,并处理更多流量。

  • Express并发限制受Nodejs进程并发限制的约束,该限制受cpu / memory / network的性能限制。它不是您设置或调整的数字,它取决于硬件性能。(更好的性能,更多的并发性) (2认同)