我们正在创建一个能够跨多个地理站点分发任务的网站.该网站应该能够:
创建一个任务,
把它放在队列中,
根据地理标准将其分配给工人,
根据工作状态更新Web界面(步骤1,2 3等),
将最终结果保存在mongodb中并注意Web界面.
只要不符合相同的地理标准,我们就可以开展并行工作.
我们可以删除作业,只要它不处于处理状态.
我们目前的堆栈是:Angulajs - nodejs - mongodb.
我们的第一个想法是建立从远程工作者到mongodb任务的HTTP池.关键是我们将有超过20名远程工作人员,我们希望高频刷新(<1s).我们认为这个解决方案易于实现,但很难维护并使DB过载.此解决方案高度依赖于网络ping.
经过网上的一些研究,我们找到了关于rabbitMQ和消息系统的文档.这似乎符合我们的大部分要求,但我不知道如何删除处于暂挂状态的队列中的特定作业以及我们如何轻松处理任务状态的更新.
我们还找到了关于redis的文档,这是一个RAM中的KV系统.这解决了能够删除队列中的特定任务并减少mongodb负载的问题,但我们没有看到我们如何能够注意到工作中的远程工作人员要做的事情.如果是HTTP池,我们就失去了所有的好处.
我们的情况似乎是一个常见的问题,我想知道最好的解决方案是什么?
Redis很棒,因为你可以将它用于除了工作队列之外的其他功能,比如缓存.我个人使用Kue.跨数据中心的Kueing工作可能不是最佳决策.虽然我不了解您的情况,但我们普遍认为您的数据模型应集中在您的内容分发的位置.我在San Fransisco运行一个托管API的服务,并在San Fran和NYC拥有CDN节点.我的内容是服务器端模板,图像,脚本,CSS等.我的API可以完全填充.
如果你绝对需要这个功能我个人建议iron.io.他们提供2种服务,可以解决您的问题.首先,它们通过RESTful API提供MQ系统,它非常易于使用,并且与节点完美配合.它还提供了一个Worker服务,允许您在其堆栈上排队,计划和运行任务.如果您需要从您自己的云访问资源,这将是限制,在这种情况下,我会建议ironMQ.
如果您不想外包服务,并且想要托管MQ,我不建议使用rabbitMQ进行作业排队.我建议像beanstalkd那样更适合作业排队,而RabbitMQ更适合于消息排队(谁是thunk?).
在阅读了一些其他答案的一些评论之后,我觉得beanstalkd可能是你最好的方法.它更适用于作业排队,而许多其他MQ系统会发送有关更新的消息并实时在云中推送新数据,您必须在此基础上实现自己的作业排队系统.
Rabbit MQ,Redis和ZeroMQ非常棒,但是你可以在不离开mongoDB的情况下完成它.有一些名为capped collection的特殊集合允许流式传输,它们对于数据库来说非常快速且便宜.您可以让您的工作人员(或其他进程)监听队列,然后执行任务.
例如,假设您为每个区域都有一名工作人员,并且所述区域都标有字符串.然后我们只需要创建一个内部队列来处理主逻辑中的更新.我们将使用mongoose和async来显示它:
var internalQueue = async.queue(function (doc, callback) { doc.status = 2; doc.save(function(e){ // We update the status of the task // And we follow from here, doing whatever we want to do }) }, 1); mongoose .TaskModel .find({ status: 1, region: "KH" // Unstarted stuff from Camboya }) .stream() .on('data', function (doc){ internalQueue.push(doc, function(e){ console.log('We have finished our task, alert the web interface or save me or something'); }); });
也许您不想使用mongoose或async,或者想要使用每个区域的地理查询或多个工作程序,但您可以使用已有的工具执行此操作:mongoDB和Node.js
要开始使用上限集合,只需在mongoDB终端上使用createCollection:
db.createCollection('test', {capped: true, size: 100*1000, max: 100} )
记住两件事:
数据将根据插入顺序而不是时间或上次访问该文档而到期,因此您的集合足够大.
您无法删除文档,但只需将其清空即可