使用多线程请求从API中抓取JSON数据

时间:2016-01-06 17:04:35

标签: ruby multithreading

我正在使用httparty发出请求,目前有以下代码:

def scr(users)
  users.times do |id|
    test_url =  "siteurl/#{id}"
    Thread.new do     
      response = HTTParty.get(test_url)

      open('users.json', 'a') do |f|
        f.puts "#{response.to_json}, "
      end
      p "added"
    end
  end
  sleep    
end

适用于100-300条记录。

我尝试在Thread.exit之后添加sleep,但是如果我将用户设置为200000,过了一段时间我的终端会抛出错误。我不记得它是什么,但它是线程的东西......资源很忙,但有些记录。 (成功添加了大约10000个。)

看起来我做错了,需要以某种方式中断批量请求。

这是我得到的:

def scr(users)
 threads = []
 urls = []

 users.times do |id|
   test_url = "site_url/#{id}"
   urls<<test_url
 end

  urls.each_slice(8) do |batch|
    batch.each do |t|
      threads << Thread.new do
        response = HTTParty.get(t)
        response.to_json
      end
    end 
  end   

 all_values = threads.map {|t| t.value}.join(', ')
 open('users.json', 'a') do |f|
  f.puts all_values
 end

1 个答案:

答案 0 :(得分:1)

在快速检查时,问题似乎是您的JSON文件存在竞争条件。即使您没有收到错误,您肯定会收到损坏的数据。

最简单的解决方案可能只是在最后完成所有的写作:

  def scr(users)
   threads = []
   users.times do |id|
     test_url =  "siteurl/#{id}"
     threads << Thread.new do     
       response = HTTParty.get(test_url)
       response.to_json
     end
   end
   all_values = threads.map {|t| t.value}.join(', ')
   open('users.json', 'a') do |f|
    f.puts all_values
   end
  end

无法测试,但应该可以解决问题。一般来说,使用Thread#joinThread#value代替sleep也会更好。