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



使用完全联系API,但它们的速率限制为300次调用/分钟。我目前有它设置在上传电子邮件的 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

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

我目前正在处理一个类似的问题,API 限制为每 0.5 秒 1 个请求,每天最多 1000 个。我还没有弄清楚如何跟踪每天的使用量,但是我已经使用线程处理了每秒的限制。如果您可以将限制框定为"每 0.2 秒 1 个请求",这可能会使您不必每分钟跟踪它(尽管您仍然有如何跟踪多个工作线程的问题)。

基本思想是,我有一个请求方法,该方法将单个请求拆分为请求参数队列(基于 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 的"超额配额"响应。在这些情况下,请求将在经过适当的间隔后重试。

最新更新