Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ECONNRESET in Express.js (Node.js) with multiple requests

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();
});
like image 836
Tamas Avatar asked Nov 16 '18 15:11

Tamas


People also ask

CAN node js handle multiple requests?

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.

How do I fix Econnreset error?

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.

How many requests can node Express handle?

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.


1 Answers

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 .

like image 123
Mazki516 Avatar answered Oct 14 '22 14:10

Mazki516