Учитывая стандартную настройку 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.info(data)).catch(error => console.error(error));
}
Однако я вижу возвращенные данные, время от времени я вижу ошибку 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.info(result);
return result;
} catch(e) {
console.info(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.info(`${worker.id} removed`);
cluster.fork();
});
обновил код, теперь в некоторых случаях я получаю ECONNREFUSED из выборки.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Одна из причин, по которой вы это видите, заключается в том, что вы звоните «параллельно». Вы запускаете вызовы один за другим, но циклы заканчиваются, вероятно, до того, как сервер вернет первые результаты. Цикл продолжается до конца, в результате чего стек вызовов заполняется 1000 асинхронными запросами к серверу.
Вы выходите за пределы аппаратного / программного обеспечения, и с кодом все в порядке. Если вы действительно хотите создать сервер, который может одновременно обрабатывать 1 КБ (и многое другое) запросов, я бы посмотрел на «кластерный» модуль узла.
Обратите внимание, что при выполнении сетевой работы между серверами допустимо использовать ограничение параллелизма. (например: до 4 запросов одновременно)
но вы всегда можете масштабировать свой сервер за пределы одной машины и обрабатывать гораздо больше трафика.
Есть ли способ увеличить лимит? Не могли бы вы подробнее рассказать о параллельных запросах?
Вы всегда можете попробовать настроить ограничения файловых дескрипторов (уровень ОС) и таймауты (на экспресс-сервере). но это всего лишь «мелкие» исправления, а не реальное решение. Пожалуйста, ознакомьтесь с модулем кластера, чтобы вы быстро узнали, как масштабировать свое приложение за пределами однократного процесса (многоядерный сервер).
Что касается параллелизма, Nodejs основан на архитектуре, управляемой событиями, где вы помещаете задачи в очередь и ждете их завершения. вы первый код, только что создали 1k запросов, не дожидаясь завершения некоторых из них раньше других. Это плохая практика, особенно при работе с вводом-выводом (сеть, файловая система). Опять же, если вы хотите «больше мощности» / «сока»;), масштабируйте свое приложение и убедитесь, что вы не помещаете много задач в очередь.
Знаете ли вы, как установить ограничение параллелизма в приложении Express?
Ограничение экспресс-параллелизма ограничено ограничениями параллелизма процесса Nodejs, которые ограничены производительностью вашего процессора / памяти / сети. это не число, которое вы устанавливаете или настраиваете, и оно зависит от производительности оборудования. (лучшая производительность, больше параллелизма)
Вы пытаетесь использовать действие
aync(выборка) в кодеsync(цикл for). См. это, может это поможет.