【问题标题】:Queuing API calls to fit rate limit排队 API 调用以适应速率限制
【发布时间】:2015-02-05 19:33:46
【问题描述】:

使用 Full Contact 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

【问题讨论】:

  • 如何处理来自第 3 方的 rate_limit 异常并在 60 秒后重新安排作业

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


【解决方案1】:

这里有几个问题需要考虑 - 是否会有一个进程在任何时候使用您的 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 收到“超出配额”的响应。在这些情况下,会在经过适当的时间间隔后重试请求。

【讨论】:

    猜你喜欢
    • 2022-11-13
    • 1970-01-01
    • 2020-12-05
    • 1970-01-01
    • 1970-01-01
    • 2020-11-04
    • 1970-01-01
    • 2014-08-05
    相关资源
    最近更新 更多