排队API调用以适应速率限制

时间:2013-09-08 21:29:09

标签: ruby-on-rails ruby-on-rails-3 delayed-job rate-limiting fullcontact

使用Full Contact API,但速度限制为300calls /分钟。我目前要设置它在上传电子邮件的CSV文件时进行API调用。我想排队,一旦它达到速率限制或300次通话,它等待1分钟然后继续。然后我会把delayed_job放在上面。我怎样才能做到这一点?快速解决方法是使用

sleep 60 

但是我如何找到它已经进行了300次调用,让它睡眠或将它排队等待下一组呢?

def self.import(file)
    CSV.foreach(file.path, headers: true) do |row|
        hashy = row.to_hash
        email = hashy["email"]
        begin
        Contact.create!(email: email, contact_hash: FullContact.person(email: email).to_json) 
        rescue FullContact::NotFound
            Contact.create!(email: email, contact_hash: "Not Found")
        end
    end
end

1 个答案:

答案 0 :(得分:2)

这里有几个需要考虑的问题 - 是否会在任何时候使用您的API密钥进行单个进程,或者是否可能同时运行多个进程?如果你有多个delayed_job工人,我认为后者很可能。我没有使用delayed_jobs足以为你提供一个很好的解决方案,但我的感觉是你只能被一个工人限制。

我目前正在处理类似的API问题,每0.5秒限制1次请求,每天最多1000次。我还没有弄清楚我想跟踪每天的使用情况,但我已经使用线程处理了每秒限制。如果您可以将限制设置为“每0.2秒1个请求”,则可能使您无需每分钟跟踪一次(尽管您仍然遇到如何跟踪多个工作人员的问题)。 / p>

基本思想是我有一个请求方法,将单个请求拆分为请求参数队列(基于api每个请求允许的最大对象数),然后另一个方法迭代该队列并调用一个块,它将实际请求发送到远程服务器。像这样:

def make_multiple_requests(queue, &block)
  result = []
  queue.each do |request|
    timer = Thread.new { sleep REQUEST_INTERVAL }
    execution = Thread.new { result << yield(request) }
    [timer, execution].each(&:join)
  end
  result
end

使用它:

make_multiple_requests(queue) do |request|
  your_request_method_goes_here(request)
end

这里的主要好处是,如果请求的时间超过允许的时间间隔,则无需等待sleep完成,您可以立即开始下一个请求。它只是保证下一个请求直到至少间隔已经过去才会开始。我注意到即使间隔设置正确,我偶尔会从API获得“超额配额”响应。在这些情况下,请求在适当的时间间隔过后重试。