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
错误消息的数量也各不相同:有时我收到一些,有时更多。我确实理解该消息,但我无法解决它背后的问题。
这是一个示例错误:
{ 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();
});
您看到此消息的原因之一是您在 "parallel" 中进行了调用。
您确实一个接一个地开始调用,但循环可能会在服务器返回第一个结果之前结束。
循环一直持续到结束,使调用堆栈充满了对服务器的 1000 个异步请求。
您正在达到 hardware/software 限制,代码没有任何问题。
如果您确实想构建一个可以同时处理 1k(以及更多)请求的服务器,我会查看节点的 "cluster" 模块。
请注意,在服务器之间进行网络作业时,使用并发限制是可以接受的。 (例如:最多并发 4 个请求)
但您始终可以将服务器扩展到一台机器之外并处理更多的流量。
给定标准 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
错误消息的数量也各不相同:有时我收到一些,有时更多。我确实理解该消息,但我无法解决它背后的问题。
这是一个示例错误:
{ 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();
});
您看到此消息的原因之一是您在 "parallel" 中进行了调用。 您确实一个接一个地开始调用,但循环可能会在服务器返回第一个结果之前结束。 循环一直持续到结束,使调用堆栈充满了对服务器的 1000 个异步请求。
您正在达到 hardware/software 限制,代码没有任何问题。 如果您确实想构建一个可以同时处理 1k(以及更多)请求的服务器,我会查看节点的 "cluster" 模块。
请注意,在服务器之间进行网络作业时,使用并发限制是可以接受的。 (例如:最多并发 4 个请求)
但您始终可以将服务器扩展到一台机器之外并处理更多的流量。