自行重新排列作业队列的方法

时间:2011-01-02 04:57:45

标签: perl design-patterns parallel-processing amazon-sqs job-queue

我有一个作业队列(使用Amazon SQS),它将作业交给许多机器,用于通过HTTP获取和处理各种文档。有数百个不同的主机被访问,并且没有可预测的作业顺序。

为了礼貌,我不希望我的系统在一台主机上反复敲击。因此,如果我得到一份工作#123从example.com获取某些内容,但我发现我在过去的X秒内刚刚从example.com获取了另一件事,我应该转向其他内容并保存作业#123 for后面。

问题是,实施这种模式的好方法是什么?

似乎第一步是让作业运行者在所有域的某个位置保留一个列表,并且最后一次访问该域上的某些内容。我想这可能是一个简单的数据库表。

如果消息处理器获得必须延迟的作业,那么有很多可能的选项可供选择。

  1. 只需将邮件的副本推送到队列的末尾,然后将其丢弃而不执行它。希望在下一次出现时,足够的时间过去了。这可能会导致大量冗余SQS消息,特别是如果同一域的大型作业集合同时发生。

  2. 在礼貌要求可以执行作业之前,需要休息几秒钟。这可能导致许多队列处理器同时无所事事。

  3. 接受作业,但将其保存在每个队列处理器上某处的本地队列中。我想每个处理器都可以通过这种方式“声称”一些工作,然后选择以任何顺序处理它们以达到最大程度的礼貌。这仍然是不可预测的,因为每个队列处理器都需要知道所有其他队列所遇到的域。

  4. 为每个域建立单独的队列,并为每个队列分配一个进程。每个进程必须在执行每个作业之间暂停X秒,因此会有很多睡眠过程开销,但这可能不是一件坏事。

  5. 你有设计这类东西的经验吗?你会推荐什么策略?

2 个答案:

答案 0 :(得分:2)

为每个域和域队列分隔队列。

每个处理器应该:

  1. 从域名队列中选择一个域。
  2. 如果最近未更新域,请从域队列中选择顶级任务。
  3. 将域放回域名队列的末尾。
  4. 如果我们要执行任务,请执行此操作。
  5. 睡眠,直到检查域队列的头部或更新域队列为止。
  6. 如果将域队列组织为时间优先级队列,则可能会有所帮助 - 按照下一个更新时间的顺序存储域。

答案 1 :(得分:0)

我建议为每个域设置一个队列,每个队列设置一个处理器。

大多数服务器应该对串行发出的请求没有问题,只要您密切关注总传输数量(例如,除非有实际需要,否则应避免将文件索引超过几百KB)为了它)。

我认为你也遵守robots.txt规则。