使用特定于用户的队列进行后台处理?

时间:2013-11-15 11:48:49

标签: ruby-on-rails ruby background-process resque sidekiq

我一直在使用Sidekiq来处理后台工作,但我发现它对我的特定用例来说太有限了。

当用户创建帐户时,我们会从第三方服务导入他们的数据。该服务有一个速率限制,所以我可以抛出几十个工人来加速进口。

问题在于我无法控制使用Sidekiq的工作人员数量。

我可以限制每个队列的工作人员数量,但这对我没有帮助。

例如,如果10个人创建了一个帐户,我必须对所有10个人的所有数据的整体导入进行评分限制,但我真正需要的是对每个帐户进行费率限制。

实际上能够创建一个特定于用户的队列然后限制每个队列的工作者数量可能会有所帮助。

是否有类似Sidekiq的东西可以更精细地控制工人数量?

1 个答案:

答案 0 :(得分:0)

我有类似的情况,我需要自我施加速率限制,以避免DDoSing外部服务。我使用Sidetiq来控制Sidekiq作业的排队。

使用Sidetiq,您可以定期对Sidekiq作业进行排队。在您的情况下,您可以创建一个Sidetiq作业,例如,每小时向Sidekiq添加10个用户导入作业。

class UserJobScheduler
  include Sidekiq::Worker
  include Sidetiq::Schedulable

  recurrence { hourly.minute_of_hour(0) }

  sidekiq_options queue: :default

  def perform
    # find 10 unprocessed user ids, then queue them up
    User.where(unprocessed: true).limit(10).pluck(:id).each do |user_id|
      UserDataImporter.perform_async(user_id)
    end
  end
end

class UserDataImporter
  include Sidekiq::Worker

  sidekiq_options queue: :user_import, retry: false

  def perform(user_id)
    # import user data & mark as processed
  end
end

我在实际调用我需要速率限制的API的类中将重试设置为false。这允许更精确地控制发送的请求的数量。否则,失败的请求将遵循Sidekiqs重试计划,这可能对您正在呼叫的服务过于激进

然后,您可以调整UserJobScheduler中每次运行添加的作业数量,以及将它们添加到Sidekiq队列并使用重复设置的频率,使其低于您正在调用的API的速率限制。