6

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

为了礼貌,我不希望我的系统反复锤击单个主机。因此,如果我得到一个作业 #123 来从 example.com 获取一些东西,但我发现我刚刚在过去 X 秒内从 example.com 获取了另一个东西,我应该继续做其他事情并将作业 #123 保存为之后。

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

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

如果消息处理器获得必须推迟的工作,那么有许多可能的选择。

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

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

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

  4. 为每个域建立单独的队列,并为每个队列设置一个专用进程。每个进程在执行每个作业之间都必须暂停 X 秒,因此有很多睡眠进程开销,但这也许不是一件坏事。

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

4

2 回答 2

2

每个域的单独队列和域队列。

每个处理器应该:

  1. 从域队列中选择一个域。
  2. 如果域最近没有更新,请从域队列中选择最上面的任务。
  3. 将域放回域队列的末尾。
  4. 如果我们有任务要执行,那就去做吧。
  5. 休眠直到检查域队列的头部或域队列被更新。

如果您将域队列组织为时间优先队列,这可能会有所帮助——按照下一次更新时间的顺序存储域。

于 2011-01-02T06:06:07.203 回答
0

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

大多数服务器对于连续发出的请求应该没有问题,只要您关注总传输量(例如,您应该避免索引超过几百 KB 的文件,除非您确实需要它) .

我假设您也遵守 robots.txt 规则。

于 2011-01-02T05:07:18.963 回答