3

我的 Heroku Rails 应用程序维护着大量频繁更改的关键字列表。

我想产生 N 数量的工人,它们将平均划分这个关键字列表并对其进行处理,直到它们重新启动(每次关键字列表更改时我都会重新启动它们)。一旦重新启动,他们就会再次划分关键字并流失。

例如:假设我有 1,000 个关键字。

  • 如果我生成 1 个工人,该工人将接受 1,000 个关键字。
  • 如果我产生 10 个工人,每个工人将使用 100 个关键字。
  • 如果我产生 1,000 个工人,每个工人将使用 1 个关键字。

工作人员基本上只是为他们的一组关键字打开与 Twitter 的连接,并处理与这些关键字匹配的传入推文。

关于如何在 N 个工作人员之间设置 Procfile 和委托 X 关键字的任何想法?


这是一种天真的/伪手动方法,仅用于演示。但是,我希望能够产生任意数量的工人,它们会自动在它们之间分割关键字。

档案:

keywordstreamer0: bundle exec ruby keyword_streamer.rb 0
keywordstreamer1: bundle exec ruby keyword_streamer.rb 1

关键字流媒体.rb

streamer_id = ARGV.shift # 0 or 1

# Split all keywords into array of two groups and take the group
# that matches this worker id (so the two workers take different groups)
keywords = Keyword.all.split_into_groups_of(2)[streamer_id]

# Example work loop
TwitterStream.track(keywords).each do |incoming_tweet|
  process(incoming_tweet)
end

然后,在我的应用程序中,当我需要重新启动关键字工作者时:

["keywordstreamer0", "keywordstreamer1"].each do |streamer|
  restart(streamer)
end

我希望能够产生 N 数量的这些工人,但我在分配解决方案时遇到了麻烦。我将不胜感激任何高级概述建议!

4

1 回答 1

3

如果您一次只处理一个关键字,没有特定的顺序或分组,您可以只使用队列。

每个工作人员只需从队列中取出下一个关键字(或者可能是下一批关键字,以提高性能),完成工作,然后将结果保存在某处。您无需担心对工作负载进行分区,因为工作人员在准备好后只会要求更多工作,从而允许您扩展到 N 个工作人员,而无需每个工作人员都知道可用工作负载的总大小。

您可以通过多种方式为数据实现队列。我之前使用过的一些更专业的是 AMQP 和 Redis,但这并不是一个详尽的列表。

我要猜测一下,既然你已经Keyword.all在你的示例代码中,并且你在 Heroku 上,那么你正在使用 postgres。您也可以在 postgres 中轻松模拟队列,尽管它的性能显然不如专门构建的队列。

这是一种方法:

status为您的关键字添加一列。它将有 3 个值:就绪、进行中和完成。status 列的默认值是 ready。

您的工作人员的伪代码如下所示:

loop do
  keyword = Keyword.where(:status => "ready").limit(1).first
  keyword.update_attributes!(:status => "in-progress")

  result = process(keyword)
  save_result_somewhere(result)

  keyword.update_attributes!(:status => "complete")
end

我遗漏了一堆实现细节,比如优雅地处理队列为空、队列的初始设置、批处理等。但这就是它的要点。对于适度规模的 N(可能至少 10 个或更多工人),这应该足够执行。除此之外,您可能还需要考虑专门构建的排队技术。

设置队列后,每个工作人员都是相同且自主的。就heroku ps:scale worker=N这样,你就完成了!

于 2012-11-01T21:53:31.167 回答