2017-05-19 47 views
0

我目前正在开发一个Rails应用程序,它需要一长串链接作为输入,使用后台工作人员(Resque)擦除它们,然后将结果提供给用户。但是,在某些情况下,有很多URL,我希望能够并行/并发地发出多个请求,这样会花费更少的时间,而不是等待一个请求完成到一个页面,然后抓取它,并且前进到下一个。如何用Rails和Heroku制作多个并行并发请求

有没有办法在heroku/rails中做到这一点?我在哪里可以找到更多信息?

我遇到了resque-pool,但我不确定它是否可以解决此问题和/或如何实施。我还了解了使用不同类型的服务器来运行rails以使并发成为可能,但不知道如何修改我的当前情况以利用它。

任何帮助将不胜感激。

回答

1

请勿使用Resque。改为使用Sidekiq

Resque在单线程进程中运行,这意味着工作人员同步运行,而Sidekiq在多线程进程中运行,这意味着工作人员在不同线程中异步/同步运行。

请确保您为每个工作人员分配了一个URL。如果一个工作人员抓取多个网址,这是没有用的。

使用Sidekiq,您可以将链接传递给工人,例如,

LINKS = [...] 
LINKS.each do |link| 
    ScrapeWoker.perform_async(link) 
end 

perform_async实际上并不执行作业的时候了。相反,链接与工作者类一起放入redis的队列中,等等,以后(可能是毫秒),工作人员被分配在其自己的线程中通过运行perform实例方法在队列中执行每个作业ScrapeWorker。 Sidekiq将确保在工作人员执行期间发生异常时再次重试。 PS:你没有传递给工作人员的链接。您可以将链接存储到表中,然后将记录的id传递给工作人员。

More info about sidekiq

+0

我会看看Sidekiq。后者关于每个工作者一个URL是否对我有意义,但是我对如何知道所有URL何时被刮掉的过程感到困惑?思考? – Kevin

+0

@Kevin看到我编辑的答案。 – Adrian

+0

嗨艾德里安,我仍然困惑。所以我会调用上面的Scrapeworker.perform_async(链接),然后我会调用Scrapeworker.perform,然后它会在不同的线程中同时在async中执行队列中的所有作业?它会暂停/处理,直到解决了URL被完成时的问题。 – Kevin

0

加入这两行代码也将让你等到最后作业完成,然后再继续:

  • 此行能够确保你的计划至少一个作业等待入队之前检查所有的工作都完成,以避免误解未填充的队列中的所有作业的完成

sleep(0.2) until Sidekiq::Queue.new.size > 0 || Sidekiq::Workers.new.size > 0

  • 此行能够确保你的程序等待,直到所有工作完成后

sleep(0.5) until Sidekiq::Workers.new.size == 0 && Sidekiq::Queue.new.size == 0