【问题标题】:node.js cluster module not helping how I thought it wouldnode.js 集群模块对我的想法没有帮助
【发布时间】:2021-12-11 23:10:23
【问题描述】:

我最近了解了 node 中的 cluster 模块,并想试一试。我有一个超级基本的快递应用,看起来像这样。

const express = require('express');
const app = express();
const cluster = require('cluster');
const os = require('os');

const numCores = os.cpus().length;

app.get('/', (req, res) => {
    res.status(200).json({ success: true })
});

if (cluster.isMaster) {
    for (let i = 0; i < numCores; i++) {
        cluster.fork();
    }

    cluster.on('exit', (worker, code, signal) => {
        console.log(`worker ${worker.process.pid} died`);
        console.log("Let's fork another worker!");
        cluster.fork();
    });

} else {
    app.listen(1337, () => console.log('server is running on port 1337'));
}

我也在使用 Artillery 负载测试工具对这个基本节点应用进行负载测试。

问题是,无论我是否使用cluster 模块,当我的负载测试运行完成时,我有相同数量的失败请求。

这是我的测试结果

推出的场景:30000 完成的场景:23145 完成的请求:23145 平均响应/秒:426.14 响应时间(毫秒): 分钟:0 最大:449 中位数:1 p95:4 p99:35 场景计数: 简单请求:30000 (100%) 代码: 200: 23145 错误: ETIMEDOUT:6855

为什么即使我使用cluster 模块,我也会有6855 ETIMEDOUT 错误? 这与我不使用 cluster 模块时出现的错误数量完全相同。

【问题讨论】:

  • 您是否尝试过在中间件中打印进程 ID?看看它们是否实际上是由不同的进程处理的。你是不是也用服务器作为客户端来进行压力测试?
  • 我刚刚尝试打印进程 id,每个请求都有不同的 pid。我正在从 CLI 运行测试
  • 基于这个答案,这似乎是预期的行为,因为节点是单线程在这里读取:stackoverflow.com/a/28737438/6356919
  • 这并不是答案所说的。您应该期待一些性能提升,尽管很小,具体取决于您拥有的内核数量。问题也是几乎没有做任何 CPU 限制的事情,即便如此,他确实获得了性能提升。
  • 正确,正如您将看到的,我尝试实现下面的答案,虽然它确实提高了一点性能,但老实说可以忽略不计。这就是为什么我认为我评论中的链接答案也回答了我的问题

标签: javascript node.js node-cluster


【解决方案1】:

您可能只需要在孩子内部定义处理程序:

const express = require('express');
const cluster = require('cluster');
const os = require('os');

const numCores = os.cpus().length;

if (cluster.isMaster) {
    for (let i = 0; i < numCores; i++) {
        cluster.fork();
    }

    cluster.on('exit', (worker, code, signal) => {
        console.log(`worker ${worker.process.pid} died`);
        console.log("Let's fork another worker!");
        cluster.fork();
    });
} else {
  const app = express();
  app.get('/', (req, res) => {
    let result = -1;
    console.time();
    for (let i = 0; i < 2 ** 28; i += 1) {
      result += i;
    }
    console.timeEnd();
    res.status(200).json({ result });
  });
  app.listen(1337, () => console.log('server is running on port 1337'));
}

我也会把const app = express() 放在里面。

我认为在 fork 之前定义处理程序会导致问题。

查看:Using cluster in an Expressjs app


我认为情况是您的服务器实现的瓶颈不是处理能力,而是其他地方,例如 IO 或内存。

如果您在处理程序中添加一些逻辑(请参阅上面更新的脚本),当只有 1 个工作人员时,如果您有一台四核机器,CPU 利用率将最高约为 25%。

我没有Artillery,所以我使用以下脚本在本地进行测试。

const fetch = require('node-fetch');

const CONCURRENT_REQUEST = 8;
let numberOfRequest = 100 - CONCURRENT_REQUEST;
let failed = 0;

const ping = () => (
  fetch('http://localhost:1337')
    .then(r => r.json())
    .then(({ success }) => {
      if (!success) {
        throw new Error('oops');
      }
    })
    .catch((e) => {
      // console.error(`index ${i}`, e);
      failed += 1;
    })
    .then(() => {
      numberOfRequest -= 1;
      if (numberOfRequest > 0) {
        return ping();
      }
    })
);

const requests = new Array(CONCURRENT_REQUEST).fill(0).map((_, i) => (
  ping()
));

Promise.all(requests).then(() => console.log('done. failed: ', failed));

只有 1 名工人:

Minutes           : 1
Seconds           : 1
Milliseconds      : 199
TotalDays         : 0.000708324185185185
TotalHours        : 0.0169997804444444
TotalMinutes      : 1.01998682666667
TotalSeconds      : 61.1992096
TotalMilliseconds : 61199.2096

有 4 名工人:

Seconds           : 17
Milliseconds      : 249
Ticks             : 172490478
TotalDays         : 0.000199641756944444
TotalHours        : 0.00479140216666667
TotalMinutes      : 0.28748413
TotalSeconds      : 17.2490478
TotalMilliseconds : 17249.0478

【讨论】:

  • 我试过这个并在worker中添加了const app = express(),这有点帮助,我的总错误现在从6855下降到5609。我仍然觉得这不对
  • CPU 使用率是否已满?
猜你喜欢
  • 1970-01-01
  • 2018-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-17
  • 2011-09-21
  • 2011-03-17
  • 1970-01-01
相关资源
最近更新 更多