Ruby on Rails同时进行多个HTTP请求?

10

我正在拉取多个请求(一次只拉取一个),我想知道如果我有像这样的东西,是否有一种方式可以同时拉取所有请求:

client = Instagram.client(:access_token => session[:access_token])
@user = client.user
@recent_media_items = client.user_recent_media

@lv = client.tag_recent_media('lv', options = {:count => 60})
@lv1 = client.tag_recent_media('lv1', options = {:count => 60})
@lv2 = client.tag_recent_media('lv2', options = {:count => 60})
@lv3 = client.tag_recent_media('lv3', options = {:count => 60})

每个 lv 都向 client 发出请求。我想知道是否有一种方法可以让它们一次性(一起)完成所有请求,而不是一个完成请求,然后再进行下一个请求,以此类推...

谢谢!

2个回答

14
是的!作为概念验证,请尝试。
require 'thread'

client = Instagram.client(:access_token => session[:access_token])
@user = client.user
@recent_media_items = client.user_recent_media

threads = []
threads << Thread.new { @lv = client.tag_recent_media('lv', options = {:count => 60}) }
threads << Thread.new { @lv1 = client.tag_recent_media('lv1', options = {:count => 60}) }
threads << Thread.new { @lv2 = client.tag_recent_media('lv2', options = {:count => 60}) }
threads << Thread.new { @lv3 = client.tag_recent_media('lv3', options = {:count => 60}) }
threads.each(&:join) # this waits for all the threads to finish before proceeding
puts [@lv, @lv1, @lv2, @lv3]

在实践中,您将需要在线程内设置一些错误处理和重试设置。此外,在Instagram gem中可能会遇到线程安全问题。如果您在大规模上进行此操作,例如数百或数千个请求,那么您可能希望尝试使用并发HTTP客户端,例如Typhoeus或事件驱动的HTTP客户端,例如EM-HTTP-Request。对于这些客户端,您需要手动实现Instagram gem中的tag_recent_media方法。


哇塞,我觉得这个好像成功了!嗯,如果我在生产环境中只是这样做的话,应该没问题吧? - hellomello
3
是的,但你可能需要一些错误处理。如果其中一个线程发生异常,threads.each(&:join) 将抛出异常。然后,您可以使用 Thread#status 检查哪些线程发生了异常。您还可以在线程块内使用类似 retryable 的东西来处理网络错误。 - Benjamin Manns
你的示例中每个 Thread.new {...} 前面不是缺少了 threads << 吗? - Patrick Oscity

5

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接