簡體   English   中英

具有多個請求的Express.js(Node.js)中的ECONNRESET

[英]ECONNRESET in Express.js (Node.js) with multiple requests

給定標准的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));

我在端點上再次發出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));
}

我確實看到了返回的數據,但我ECONNRESET看到一個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' }

請注意,我已嘗試使用axios發出請求,內置的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();

現在我偶爾會收到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();
});

您看到這一點的原因之一是因為您以“並行”方式進行調用。 你一個接一個地啟動調用,但循環可能會在服務器返回的第一個結果之前結束。 循環一直持續到結束,使調用堆棧充滿了1000個異步請求到服務器。

你的硬件/軟件限制達到了極限,代碼沒有任何問題。 如果您確實想要構建一個可以同時處理1k(以及更多)請求的服務器,我將查看節點的“集群”模塊。

請注意,在服務器之間執行網絡作業時,可以使用並發限制。 (例如:最多同時發出4個請求)

但是您可以隨時將服務器擴展到一台計算機之外並處理更多流量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM