Given a standard Express.js setup
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));
I am making 1000 requests agains the endpoint, one after the other:
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));
}
I do see the data returned however, every now and then I see an ECONNRESET
error. The amount of ECONNRESET
error messages also vary: sometimes I get a few, sometimes a lot more. I do understand the message but I can't get my head around solving the issue behind it.
Here's a sample error:
{ 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' }
Note that I have tried to make the request using axios, the built-in HTTP module all to avail. I'm sure the issue is with my Express app handling the request but not sure how to fix it exactly.
Update 1:
As per the suggestion in the comment, here's the async version:
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();
Now I am receiving occasional ECONNREFUSED
messages.
Update 2:
Based on Mazki516's answer here's the solution that works:
// 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();
});
The entire NodeJS architecture is not single-threaded. How NodeJS handle multiple client requests? NodeJS receives multiple client requests and places them into EventQueue. NodeJS is built with the concept of event-driven architecture.
Unblock yourselfMake sure there is no error in the configuration of your request. Look for typos, whitespaces, or invalid JSON formatting. Compare the API documentation of the service you're making a call to and verify that the below elements if required, are configured correctly in the request: The request headers.
As is, node. js can process upwards of 1000 requests per second and speed limited only to the speed of your network card. Note that it's 1000 requests per second not clients connected simultaneously. It can handle the 10000 simultaneous clients without issue.
One of the reasons you see this is because you make the calls in "parallel" . You do start the calls one after the other , but the loops will end probably before the first results returned from the server. The loop continues until the end , making the call stack filled with 1000 async requests to the server .
Your'e are hitting hardware/software limits and nothing is wrong with the code. if you did want to build a server which can handle 1k (and much more) requests concurrently I would take a look into the "cluster" module of node .
Please notice that when doing network job between server , it's acceptable to use a concurrency limit . (for example: up to 4 requests concurrently)
but you can always scale your server beyond one machine and handle much more traffic .
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With