有没有更好的方法在Ruby中异步发出多个HTTP请求?

时间:2013-07-13 05:24:01

标签: ruby http sendasynchronousrequest

我正在尝试在Ruby中发出多个HTTP请求。我知道它可以很容易地在NodeJS中完成。我正在尝试使用线程在Ruby中完成它,但我不知道这是否是最好的方法。我没有成功运行大量请求(例如超过50个)。

require 'json'
require 'net/http'

urls = [
  {"link" => "url1"},
  {"link" => "url2"},
  {"link" => "url3"}
]

urls.each_value do |thing|
    Thread.new do
        result = Net::HTTP.get(URI.parse(thing))
        json_stuff = JSON::parse(result)
        info = json["person"]["bio"]["info"]

        thing["name"] = info
    end
end

# Wait until threads are done.
while !urls.all? { |url| url.has_key? "name" }; end

puts urls

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

你的方式可能会起作用,但它会在一个繁忙的循环中结束,当它真的不需要时会占用CPU周期。更好的方法是仅在请求完成时检查您是否已完成。实现此目的的一种方法是使用MutexConditionVariable

使用互斥和条件变量,我们可以让主线程等待,当其中一个工作线程收到响应时,它可以唤醒主线程。然后主线程可以查看是否还有任何URL要下载;如果是的话,它会再次入睡,等待;否则,就完成了。

等待信号:

mutex.synchronize { cv.wait mutex }

唤醒等待线程:

mutex.synchronize { cv.signal }

您可能需要检查完成情况并在thing['name']块中设置mutex.synchronize以避免同时访问多个线程中的数据。

答案 1 :(得分:1)

您可以调用Thread#join来使主线程等待其他线程,而不是您使用的while子句。

threads = []
urls.each_value do |thing|
    threads << Thread.new do
        result = Net::HTTP.get(URI.parse(thing))
        json_stuff = JSON::parse(result)
        info = json["person"]["bio"]["info"]

        thing["name"] = info
    end
end

# Wait until threads are done.
threads.each { |aThread|  aThread.join }