具有pm2集群的Nodejs Kafka使用者

时间:2017-10-21 01:02:28

标签: node.js apache-kafka cluster-computing kafka-consumer-api pm2

我已经实现了Kafka消费者应用程序,我只是想知道我是否在pm2集群模式下运行此应用程序,所有内核是否会使用相同的消息或不同的消息?有没有办法可以验证它?并且在群集模式下运行此应用程序是否理想?我在集群模式下运行它的原因是因为我们的kafka产生了大量的消息。

目前,如果我在pm2集群模式下运行它,我们所有的内核都达到了100%的CPU使用率。它是否会发生这样的事情?

仅供参考:我正在使用https://www.npmjs.com/package/no-kafka

2 个答案:

答案 0 :(得分:3)

  

所有核心都会使用相同的消息或不同的消息吗?有没有办法可以验证它?

这取决于您的主题配置+消费者配置。我们举一个例子。

  • 假设我们有一个包含3个分区的主题。
  • 现在我们将消费者群体的1个消费者流程作为“some_consumer_group”启动。对于comsumer组的详细信息,请查看此处https://www.npmjs.com/package/no-kafka#groupconsumer-new-unified-consumer-api
  • 现在您的一个消费者正在收听3个分区。
  • 由于kafka维护每个主题的偏移量,每个消费者组的每个分区,您的消费者将从3个不同的分区接收3条消息。因此没有重复的消息。
  • 现在让我们再添加一个消费者流程。
  • 现在消费者群体“some_consumer_group”的消费者1正在侦听分区0和1,而消费者群体“some_consumer_group”的消费者2正在侦听分区2.(它可能会反过来)。
  • 最后,如果我们再向该组添加一个消费者,现在我们让每个消费者都听一个分区
  • 如果这是设置,您将不会遇到重复的消息。
  

目前,如果我在pm2集群模式下运行它,我们所有的内核都达到了100%的CPU使用率。它是否会发生这样的事情?

我并不熟悉no-kafka以及消息的处理方式。

但是检查一下,在获取下一批消息之前,库是否等待提交。

如果没有,您的进程可能会为消息创建太多处理程序。

答案 1 :(得分:3)

基于PM2的群集仅适用于网络服务器,因为群集进程共享传入网络端口并分发请求。

在您的情况下,数据源是消息订阅,必须手动将其分发到群集的工作进程。

因此,为了安全起见,主进程应该与数据源交互并将消息均匀地分发给工作进程,因此在外部,它似乎是单个使用者,但仍然可以在所有CPU上处理消息核心。

下面的示例演示了这种设置,不依赖于基于PM2的群集:

const cluster = require('cluster');
const _ = require('lodash');
const os = require('os');

// dispatch index
let dispatchIndex = 0;

/**
 * Dispatches data to workers in a cyclic fashion
 * @param {*} data - data to process
 */
function dispatch(data) {

    // ensure master
    if (!cluster.isMaster) {
        throw new Error('Only master can dispatch');
    }

    // get worker ids, sorted
    const workersIds = _.sortBy(_.keys(cluster.workers), _.identity);

    // ensure at least one worker is available
    if (workersIds.length < 1) {
        throw new Error('No worker process alive');
    }

    // select next worker
    dispatchIndex = dispatchIndex >= workersIds.length ? 0 : dispatchIndex;
    const worker = cluster.workers[workersIds[dispatchIndex]];
    dispatchIndex++;

    // send data to worker
    worker.send(data);
}


// Main Script
if (cluster.isMaster) {

    // Setup master process
    console.info(`Master ${process.pid} started.`);

    // fork worker processes to match available CPUs
    const numCpu = os.cpus().length;
    for (let i = 0; i < numCpu; i++) {
        cluster.fork();
    }

    // *** Get/Subscribe data from external source and dispatch to workers ***
    setInterval(() => dispatch({ a: 'value' }), 1000);

} else if (cluster.isWorker) {

    // Setup worker process
    console.info(`Worker ${process.pid} started.`);

    // *** handle dispatched data ***
    process.on('message', (data) => {
        console.info(`Data processed by ${process.pid}`);
    });
}

阅读cluster module documentation也很好。