te')); return $arr; } /* 遍历用户所有主题 * @param $uid 用户ID * @param int $page 页数 * @param int $pagesize 每页记录条数 * @param bool $desc 排序方式 TRUE降序 FALSE升序 * @param string $key 返回的数组用那一列的值作为 key * @param array $col 查询哪些列 */ function thread_tid_find_by_uid($uid, $page = 1, $pagesize = 1000, $desc = TRUE, $key = 'tid', $col = array()) { if (empty($uid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('uid' => $uid), array('tid' => $orderby), $page, $pagesize, $key, $col); return $arr; } // 遍历栏目下tid 支持数组 $fid = array(1,2,3) function thread_tid_find_by_fid($fid, $page = 1, $pagesize = 1000, $desc = TRUE) { if (empty($fid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('fid' => $fid), array('tid' => $orderby), $page, $pagesize, 'tid', array('tid', 'verify_date')); return $arr; } function thread_tid_delete($tid) { if (empty($tid)) return FALSE; $r = thread_tid__delete(array('tid' => $tid)); return $r; } function thread_tid_count() { $n = thread_tid__count(); return $n; } // 统计用户主题数 大数量下严谨使用非主键统计 function thread_uid_count($uid) { $n = thread_tid__count(array('uid' => $uid)); return $n; } // 统计栏目主题数 大数量下严谨使用非主键统计 function thread_fid_count($fid) { $n = thread_tid__count(array('fid' => $fid)); return $n; } ?>javascript - ECONNRESET in Express.js (Node.js) with multiple requests - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - ECONNRESET in Express.js (Node.js) with multiple requests - Stack Overflow

programmeradmin3浏览0评论

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 ment, 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();
});

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 ment, 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();
});
Share Improve this question edited Nov 16, 2018 at 16:33 Tamas asked Nov 16, 2018 at 15:30 TamasTamas 11.2k15 gold badges51 silver badges79 bronze badges 2
  • 1 You are trying to use an aync action (fetch) in a sync code (for loop). See this, maybe it helps. – lependu Commented Nov 16, 2018 at 15:45
  • updated the code, now I get ECONNREFUSED from fetch in some cases. – Tamas Commented Nov 16, 2018 at 15:55
Add a ment  | 

2 Answers 2

Reset to default 11

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 .

I faced the same issue as you, and I was able to solve with the @lependu ment (can't ment below there due to my reputation).

But basically I mapped my data array inside an await Promise.all and it worked perfectly.

In my case I switched from:

for (let i = 0; i < dataSet.length; i++) {
    const object = dataSet[i];
    const objectID = await post(url, object);
    ids.push(objectID);
}

To:

await Promise.all(dataSet.map(async (object) => {
    const objectID = await post(url, object);
    ids.push(objectID);
}));

Credits to @lependu - the answer in Using async/await with a forEach loop and the post How to use async/await inside loops in JavaScript

发布评论

评论列表(0)

  1. 暂无评论