如何使用 Rails 和 Heroku 进行多个并行并发请求

How to make multiple parallel concurrent requests with Rails and Heroku

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

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

我遇到过 resque-pool 但我不确定它是否能解决这个问题 and/or 如何实现。我还阅读了有关使用不同类型的服务器 运行 rails 以使并发成为可能的信息,但不知道如何修改我的当前情况以利用这一点。

如有任何帮助,我们将不胜感激。

不要使用 Resque。请改用 Sidekiq

Resque 运行s 在单线程进程中,意味着工人 运行 同步,而 Sidekiq 运行s 在多线程进程中,意思是工人 运行 asynchronously/simutaneously 在不同的线程中。

确保为每个工人分配一个 URL 来抓取。如果一个工人刮了多个 URLs 是没有用的。

使用 Sidekiq,您可以将 link 传递给工作人员,例如

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

perform_async 实际上并没有立即执行作业。相反,link 只是与 worker class 一起放入 redis 的队列中,依此类推,稍后(可能是几毫秒后)worker 被分配去执行自己队列中的每个作业通过 运行 在 ScrapeWorker 中调用 perform 实例方法。 Sidekiq 如果在 worker 执行期间发生异常,将确保重试。

PS: 你没有把 link 传给工作人员。您可以将 link 存储到 table,然后将记录的 id 传递给工作人员。

More info about sidekiq

将这两行添加到您的代码中还可以让您等到最后一个作业完成后再继续:

  • 此行确保您的程序在检查所有作业是否已完成之前至少等待一个作业入队,以避免将未填充的队列误解为所有作业已完成

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