我的Heroku Rails应用程序维护了一个经常更改的大型关键字列表。
我希望产生N个工作人员,这些工作人员会平均分配这个关键字列表并对其进行处理,直到重新启动它们为止(每次关键字列表更改时重新启动它们)。重新启动后,他们会再次对关键字进行分割,然后流失。
例如:假设我有1,000个关键字。
工作人员基本上只是打开与Twitter关联的关键字集,并处理与这些关键字匹配的传入推文。
有关如何在N个工作人员之间设置Procfile和委托X关键字的任何想法吗?
这是一个仅用于演示的天真/伪手动方法。但是,我希望能够产生任意数量的工作人员,这些工作人员会自动将关键字分开。
Procfile:
keywordstreamer0: bundle exec ruby keyword_streamer.rb 0
keywordstreamer1: bundle exec ruby keyword_streamer.rb 1
keyword_streamer.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
然后,在我的应用程序中,当我需要重新启动关键字worker时
["keywordstreamer0", "keywordstreamer1"].each do |streamer|
restart(streamer)
end
我希望能够产生N个这样的工人,但我在解决问题方面遇到了麻烦。我很感激任何高级概述建议!
答案 0 :(得分:3)
如果你一次只处理一个关键字,没有特定的顺序或分组,你可以只使用一个队列。
每个工作人员只是从队列中提取下一个关键字(或者可能是下一批关键字,以获得性能),是否正常工作,然后将结果保存在某处。您无需担心分区工作负载,因为工作人员只需在准备就绪时要求更多工作,允许您扩展到N个工作人员,而无需每个工作人员了解可用工作负载的总大小。 / p>
您可以通过多种方式为数据实施队列。我之前使用的几个更专业的是AMQP和Redis,但这不是一个详尽的清单。
我会猜测一下,因为你的示例代码中有Keyword.all
,而你是Heroku,那你就是在使用postgres。你也可以毫不费力地在postgres中模拟一个队列,虽然它显然不会像专用队列一样好。
这是一种方法:
在关键字中添加status
列。它将具有3个值:就绪,正在进行和完成。状态列的默认值已准备就绪。
您的工作人员的伪代码如下所示:
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
即可完成!