Ruby中的异步HTTP请求

32
 require 'net/http'

urls = [
  {'link' => 'http://www.google.com/'},
  {'link' => 'http://www.facebook.com/'},
 {'link' => 'http://www.yahoo.com/'}
]

urls.each do |u|
  u['content'] = Net::HTTP.get( URI.parse(u['link']) )
end

print urls

这段代码可以作为过程式代码运行,我只是想访问服务器,无需关心顺序。如何在ruby中实现呢?其中一种选择是使用线程。

以下是使用线程的示例:

require 'net/http'

urls = [
  {'link' => 'http://www.google.com/'},
  {'link' => 'http://www.facebook.com/'},
  {'link' => 'http://www.yahoo.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

有更好的解决方案吗..??

顺便说一句,我想调用mixpanel,所以我只想发出一个HTTP请求而不等待响应。

3个回答

15
轻量级异步处理的工作由线程(如您所说)或Fibers完成。
否则,您应该考虑使用EventMachine,这是一个非常强大的工具。
编辑:上面的Event Machine URL已经失效。这是他们的GitHub帐户,https://github.com/eventmachine/eventmachine。它可以作为一个很好的起点。

Rails,问题已标记为Rails 3 :) - Mohit Jain
RIP EventMachine(至少是发布的URL) - snowYetis

12

这里有一篇很棒的文章,涵盖了该主题。

一般来说,用于此目的的可行替代线程的方式是使用Fiber或者使用em-http-request。在后一个示例中,您可以省略特定用途的回调处理。


说纤程是线程的替代品是误导性的。纤程不能给你并发性。 - pguardiario
3
@pguardiario说:纤程绝对会在任何IO密集型任务中带来并发性能。你是正确的,对于CPU密集型任务,您需要使用多个线程,但当大多数人关心"并发性能"时,通常是为了在仅有少量处理之间执行并行网络请求。 - Dave Dopson

2
如果仅涉及以异步方式进行的纯HTTP请求,可能Unirest是实现它的最佳选择。
异步请求就像这样简单:
response = Unirest.post "http://httpbin.org/post", 
                    headers:{ "Accept" => "application/json" }, 
                    parameters:{ :age => 23, :foo => "bar" } {|response|
response.code # Status code
response.headers # Response headers
response.body # Parsed body
response.raw_body # Unparsed body
}

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