异步发出多个HTTP请求

require 'net/http' urls = [ {'link' => 'http://www.google.com/'}, {'link' => 'http://www.yandex.ru/'}, {'link' => 'http://www.baidu.com/'} ] urls.each do |u| u['content'] = Net::HTTP.get( URI.parse(u['link']) ) end print urls 

此代码以同步方式工作。 第一个请求,第二个,第三个。 我想异步发送所有请求并在完成所有请求后打印urls

最好的办法是什么? 纤维适合那吗?

我刚刚看到这一年,一年又一段时间,但希望对于一些Google员来说还不算太晚……

Typhoeus是迄今为止最好的解决方案。 它以非常优雅的方式包装了libcurl。 您可以将max_concurrency设置为大约200,而不会让它窒息。

关于超时,如果你通过Typhoeus a :timeout标志,它只会注册一个超时作为响应…然后你甚至可以把请求放回另一个九头蛇,如果你愿意再试一次。

这是用Typhoeus重写的程序。 希望这有助于以后遇到此页面的任何人!

 require 'typhoeus' urls = [ 'http://www.google.com/', 'http://www.yandex.ru/', 'http://www.baidu.com/' ] hydra = Typhoeus::Hydra.new successes = 0 urls.each do |url| request = Typhoeus::Request.new(url, timeout: 15000) request.on_complete do |response| if response.success? puts "Successfully requested " + url successes += 1 else puts "Failed to get " + url end end hydra.queue(request) end hydra.run puts "Fetched all urls!" if successes == urls.length 

这是使用线程的示例。

 require 'net/http' urls = [ {'link' => 'http://www.google.com/'}, {'link' => 'http://www.yandex.ru/'}, {'link' => 'http://www.baidu.com/'} ] urls.each do |u| Thread.new do u['content'] = Net::HTTP.get( URI.parse(u['link']) ) puts "Successfully requested #{u['link']}" if urls.all? {|u| u.has_key?("content") } puts "Fetched all urls!" exit end end end sleep 

我写了一篇关于这个主题的深入博客文章,其中包含的答案与8月份发布的内容有些相似 – 但有一些关键区别:1)跟踪“线程”数组中的所有线程引用。 2)使用“join”方法在程序结束时占用线程。

 require 'net/http' # create an array of sites we wish to visit concurrently. urls = ['link1','link2','link3'] # Create an array to keep track of threads. threads = [] urls.each do |u| # spawn a new thread for each url threads << Thread.new do Net::HTTP.get(URI.parse(u)) # DO SOMETHING WITH URL CONTENTS HERE # ... puts "Request Complete: #{u}\n" end end # wait for threads to finish before ending program. threads.each { |t| t.join } puts "All Done!" 

完整的教程(以及一些性能信息)可在此处获得: https : //zachalam.com/performing-multiple-http-requests-asynchronously-in-ruby/

这可以使用C库cURL完成 。 存在该库的ruby绑定 ,但它似乎不支持开箱即用的此function。 但是,看起来有一个补丁添加/修复它(示例代码在页面上可用)。 我知道这听起来不太好,但如果没有更好的建议,可能值得一试。

这取决于之后函数后你想要做什么。 你可以用简单的线程做到:

请参阅: http : //snipplr.com/view/3966/simple-example-of-threading-in-ruby/

您可以使用不同的线程执行Net :: HTTP.get中的每一个。 并等待所有线程完成。

BTW打印url将打印链接和内容。

work_queue gem是在应用程序中异步和并发执行任务的最简单方法。

 wq = WorkQueue.new 2 # Limit the maximum number of simultaneous worker threads urls.each do |url| wq.enqueue_b do response = Net::HTTP.get_response(url) # use the response end end wq.join # All requests are complete after this