【发布时间】:2011-06-02 09:49:08
【问题描述】:
我有一个作业队列(使用 Amazon SQS),它将作业交给许多机器,以通过 HTTP 获取和处理各种文档。有数百个不同的主机被访问,并且这些作业没有可预测的顺序。
为了礼貌,我不希望我的系统反复敲击单个主机。因此,如果我得到一个作业 #123 从 example.com 获取一些东西,但我发现我刚刚在过去 X 秒内从 example.com 获取了另一个东西,我应该继续做其他事情并将作业 #123 保存为稍后。
问题是,实现这种模式的好方法是什么?
似乎第一步是让作业运行者在某处保留所有域的列表,以及该域上的某些内容最后一次被访问的时间。我想这可能是一个简单的数据库表。
如果消息处理器得到一个必须推迟的工作,那么有很多可能的选择。
只需将消息的副本推送到队列的末尾,然后将其丢弃而不执行。希望下次它出现时,已经有足够的时间过去了。这可能会导致大量冗余 SQS 消息,尤其是在同一域的大型作业集群同时通过时。
在礼貌要求可以执行作业之前,无论多长时间都需要睡眠。这可能会导致许多队列处理器同时无所事事。
接受作业,但将其保存在每个队列处理器上某处的本地队列中。我想每个处理器都可以通过这种方式“声称”一些工作,然后选择以任何顺序处理它们以达到最大的礼貌。这仍然是不可预测的,因为每个队列处理器都需要了解所有其他队列处理器所命中的域。
为每个域建立单独的队列,并为每个队列设置一个专用进程。每个进程在执行每个作业之间都必须暂停 X 秒,因此有很多休眠进程开销,但这也许不是一件坏事。
你有设计这种东西的经验吗?你会推荐什么策略?
【问题讨论】:
-
您是否 100% 卡在 SQS 上?有一些好的设计不会强迫您进入每个域的队列解决方案,但它们要求您直接控制我假设 SQS 不提供的队列(准确地说,能够“浏览”队列而不占据顶部元素,以及获取第 N 个元素而不是顶部元素的能力 - 基本上,将队列视为没有插入的双向链表,而不是纯队列)。
标签: perl design-patterns parallel-processing amazon-sqs job-queue