多次调用集群事件消息

cluster event message called multiple times

关于下面的代码,应用程序应该在每个连接上分叉 4 个 worker,然后每个 worker 发送一条消息并断开连接。

但是,在第一次连接后,cluster.on('message') 逐渐收到消息。

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

if (cluster.isMaster) {
  const app = express();
  app.get('/', (req, res) => {
    [1, 2, 3, 4].map(() => cluster.fork());

    const count = [];
    cluster.on('message', (worker, message) => {
      console.log({
        worker: worker.id,
        message
      });
      count.push(true);
      if (count.length === 4)
        return res.sendStatus(200);
    });
  });
  app.listen(8000, () => console.log('listening on 8000'));
} else if (cluster.isWorker) {
  process.send('msg');
  process.disconnect();
}

第一个输出:

> curl localhost:8000
> { worker: 4, message: 'msg' }
> { worker: 1, message: 'msg' }
> { worker: 2, message: 'msg' }
> { worker: 3, message: 'msg' }

然后

> curl localhost:8000
{ worker: 5, message: 'msg' }
{ worker: 5, message: 'msg' }
{ worker: 8, message: 'msg' }
{ worker: 8, message: 'msg' }
{ worker: 7, message: 'msg' }
{ worker: 7, message: 'msg' }
{ worker: 6, message: 'msg' }
{ worker: 6, message: 'msg' }

等等...

我不明白为什么会这样。

您的问题源于您使用 .on("message", ...) 的方式。每次调用服务器时,您实际上都在注册侦听器。

将监听器的 'push to count' 部分移出 API 调用修复了这个问题:

if (cluster.isMaster) {
  let count = [];
  cluster.on('message', (worker, message) => {
    console.log({
      worker: worker.id,
      message
    });
    count.push(true);
  });

  const app = express();
  app.get('/', (req, res) => {
    [1, 2, 3, 4].forEach(() => cluster.fork());

    let msgHandler = (worker, message) => {
      if (count.length === 4) {
        cluster.removeListener('message', msgHandler); // Do not forget to remove this event listener, or the issue will arise again!
        count.length = 0;
        return res.sendStatus(200);
      }
    };

    cluster.on('message', msgHandler);
  });
  app.listen(10101, () => console.log('listening on 10101'));
} else if (cluster.isWorker) {
  process.send('msg');
  process.disconnect();
}