如何处理“并行”队列以保持进程饱和?

时间:2014-10-17 15:56:24

标签: node.js

我想以下列方式处理队列:

  • 队列在MongoDb中持久化(可能使用npm包" mongodb-queue")
  • 多个节点进程可以在同一个队列上运行
  • 任务涉及各种i / o,每个i / o需要0到几秒
  • 每个节点进程应同时处理最大任务

节点进程还为简单的网站(express)提供服务。但该网站的请求很少。大多数工作都将在处理队列

时完成

目标是能够比每个流程只能弹出一个流程更好地使每个流程饱和 一次任务。由于任务涉及相当多的等待外部服务我 认为如果没有在" parallell"中处理它们将是一种浪费。 (我知道它并不是真正的平行)。 我认为五个左右是极限,但这需要在一段时间后进行调整。

粗伪代码:

loopForewer {
    popNextTaskFromQueue(function(task) {
        if(task && concurrentTasks <= limit) {
            concurrentTasks ++;
            processTask(task, function(err) {
                concurrentTasks --;
            })
        })
    }
}

我该如何解决这个问题?

提前致谢。 //迈克尔


编辑:

我将详细介绍一下有关async.parallelLimit的Pauls建议和使用async.queue的尝试。我希望通过编辑我自己的问题来做到这一点。

async.parallelLimit:

实际上,我不知道这是怎么适合的。但我是Node和JavaScript的初学者,我可能错过了一些东西。

我无法在没有首先从MongoDB中的队列中获取所有可用任务的情况下看到如何保持进程饱和(即填充5个任务)。但是,如果我完成了所有任务,那么除了五个之外的所有任务都将等待而不是由另一个节点进程处理。

async.queue:

怎么看待这个?

q = async.queue.., 5) //create a queue with concurrency limit 5
dbQ = someQueueWithMongoStorage..

while(true) {
    nextTick(function() {
        if (!q.saturated) {
            dbQ.getTask(function(err, task) {
                if (task) q.push(task)
            })
        }
    })
}
  • 使用while(true)循环是否可以?
  • 还是应该递归?
  • 我在这里需要nextTick吗?我担心循环会接管事件队列。
  • 问题是当dbQ为空时我会非常关注数据库。我应该在dbQ为空时添加超时吗?

2 个答案:

答案 0 :(得分:1)

我继续尝试了async.queue概念。我将使用(种类)以下解决方案。请插入并告诉我,如果我做了一些愚蠢的事情,即锁定某些东西。当dbQ为空时,我会每隔一秒点击一次数据库,但这对我没用。

var limit = 5;

var q = async.queue(function(task, callback) {
        console.log('Processing ' + task.payload.task);
        setTimeout(function() {
            dbQ.ack(task.ack, function(err) {
                console.log('Finished ' + task.id);
                callback(); 
            })
        }, 1000);
}, limit);


function enqueueTasks() {
    console.log('QueueLength: ' + q.length() + ',  Running tasks: ' + q.running());
    if (q.length() < limit) {
        dbQ.get(function(err, task) {
            if (task) {
                console.log('Enqueing task ' + task.id)
                q.push(task, function(err) {

                });
                enqueueTasks();
            } else {
                console.log('dbQ is empty, taking a 1 second nap')
                setTimeout(function() {
                    enqueueTasks();
                }, 1000);
            }
        });
    } else {
        console.log('Queue length limit hit, taking a 1 second nap')
        setTimeout(function() {
            enqueueTasks();
        }, 1000);
    }
}

enqueueTasks();

答案 1 :(得分:0)

查看async库,特别是parallelLimit函数。

https://github.com/caolan/async#parallellimittasks-limit-callback