我正在构建一个从远程网站获取并重新验证信息的作业。事实上,我已经用一个队列实现了它,它的工作方式有点像这样:读取文本文件,然后将其分割为5k的增量,并将其交给线程处理器,然后线程处理器退出并生成一个新的工作者。
我正在研究resque,但对这样的问题有一个通用的设计问题。因此,如果我的工作可能是5-20M个工作单位,那么存储队列的最佳实践是什么?例如,理论上我可以将工作分组并存储,然后为该分组创建一个作业,或者我可以在队列中有5-20M个单独的行项目。在提取/重新生成的工作中似乎有很多开销。但也有相当大的开销和更多的编码,来尝试将工作分块。
根据我们所做的和看到的,一个好的方法是在运行时而不是之前对工作进行分块。换句话说,主/从模式是事件或时间驱动的,当它排队和运行时,主将工作/数据空间分割成细粒度的任务/块。
这样做的原因是,在粗粒度级别上查看明细表中的作业要容易得多。在这个级别上,作业对应于您正在跟踪的单元(例如,网页、用户配置文件或来自传感器的流式数据)。
我们经常看到细粒度级别的切片,但随后看到每个工作人员都在处理合理的任务集合。我们发现,让每个工人处理多个任务(20-1000?取决于任务的类型/长度)可以在以下两者之间取得良好的平衡:
- 优化设置(例如,建立数据库连接)
- 对工作进行良好的反思
- 使重试和异常处理更易于管理
您希望每个工作人员的处理时间以分钟为单位,而不是长时间运行的任务,这样您就可以更好地了解工作人员的性能,并且重试只会影响有限的工作空间。使用NoSQL解决方案(特别是像MongoHQ或MongoLabs这样的数据库即服务解决方案)可以让您轻松地跟踪和管理分块和进程中的工作。
另一个建议是创建独立于应用程序环境的辅助程序。这意味着编写每个工作程序以使其合理地自我包含,并使用回调、数据库标志和其他异步方法。这可能需要更多的工作,但就像MVC应用程序设计一样,它提供了更大的灵活性,并允许工作分布在弹性工作系统上。
(完全披露:我是Iron.io的团队成员,IronMQ、IronWorker和IronCache的制造商。)