如何避免因延迟工作而无法满足Heroku的API速率限制

时间:2013-07-12 00:47:45

标签: ruby-on-rails heroku delayed-job

My Survey模型有大约2500个实例,我需要将set_state方法应用于每个实例两次。我需要在每个实例都将方法应用于它之后第二次应用它。 (实例的状态可以取决于其他实例的状态。)

我正在使用delayed_job创建延迟作业,workless根据需要自动按比例放大/缩小我的工作人员dynos。

set_state方法通常需要大约一秒钟才能执行。所以我在heroku控制台上运行了以下命令:

2.times do
  Survey.all.each do |survey|
    survey.delay.set_state
    sleep(4)
  end
end

重载API不应该是任何问题,对吗?

然而,我仍然在每个延迟工作的日志中看到以下内容:

Heroku::API::Errors::ErrorWithResponse: Expected(200) <=> Actual(429 Unknown)

我没有看到任何无限循环 - 只要我创建延迟作业,它就会立即返回此消息。

如何避免吹Heroku的API速率限制?

1 个答案:

答案 0 :(得分:2)

回顾workless,看起来它会为每个延迟的作业发出一个API调用,以检查工作人员数量,并可能进行第二次API调用以扩大/缩小。因此,如果您在短时间内运行5000(2500x2)个作业,您最终将获得5000+ API调用。这将超过1200 /每小时限制请求。我在那里评论过希望有助于降低整体API使用率(https://github.com/lostboy/workless/issues/33#issuecomment-20982433),但我认为我们可以为您提供更具体的解决方案。

同时,特别是如果您的工作量非常可预测(如此)。我建议你自己跳过无用的工作。即听起来你已经知道需要进行缩放(在上面的循环之前放大,然后缩小)。如果是这种情况,你可以做这样的事情来模拟无效的行为:

require 'heroku-api'
heroku = Heroku::API.new(:api_key => ENV['HEROKU_API_KEY'])

client.post_ps_scale(ENV['APP_NAME'], 'worker', Survey.count)
2.times do
  Survey.all.each do |survey|
    survey.delay.set_state
    sleep(4)
  end
end
min_workers = ENV['WORKLESS_MIN_WORKERS'].present? ? ENV['WORKLESS_MIN_WORKERS'].to_i : 0
client.post_ps_scale(ENV['APP_NAME'], 'worker', min_workers)

请注意,您还需要从这些作业中删除无效工作。我没有看到某种特定的方法来为某些工作做这件事,所以如果你需要的话,你可能想问一下这个项目。此外,如果这需要2次通过(第一次通过需要在第二次之前完成),4秒睡眠可能在某些情况下是不够的,但这是一种不同的蠕虫。

我希望这有助于缩小您的需求,但我很乐意根据需要进一步讨论和/或详细说明。谢谢!