如何配置为sidekiq队列一次仅运行任务

时间:2019-03-21 12:31:23

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

我在Rails应用程序中使用Sidekiq来处理后台作业。

sidekiq.yml

:verbose: false
:pidfile: ./tmp/pids/sidekiq.pid
:logfile: ./log/sidekiq.log
:concurrency: 5
:queues:
  - ["queue1", 1]
  - ["queue2", 1]
  - ["queue3", 1]
  - ["queue4", 1]
  - ["queue5", 1]
  - critical
  - default
  - low
max_retries: 1

我希望每个队列一次只运行一个任务。

例如:我要在队列1中启动3个相同的工作程序,我想先处理worker1,然后处理worker2,然后再处理worker3。

我在sidekiq.yml中添加了带有队列名称的“ 1”(例如[“ queue1”,1])。我认为此配置将仅在queue1中运行一个工作程序。但这没有发生。

如何在sidekiq中实现以上配置?

7 个答案:

答案 0 :(得分:1)

答案 1 :(得分:1)

只需使用内置的ActiveJob,因为这听起来像您想要FIFO队列。 Sidekiq用于幂等并发背景

答案 2 :(得分:0)

queues设置控制检查队列的频率,以控制与其他队列相关的优先级,而不是将并行作业限制在该队列中。

您还可以在有限数量的线程中启动多个工作程序(这是sidekiq文档针对这种情况的建议),但是对于大多数低负载的队列(当大多数工作程序都将闲置时),这可能不切实际。

要限制一个工人中的特定队列并行作业-您可以使用gem sidekiq-limit_fetch和类似的设置:

:limits:
  queue1: 1
  queue2: 1

答案 3 :(得分:0)

Set your Sidekiq concurrency到1。这样,您的进程中将只有1个线程在工作,这将为您提供所需的输出:一次仅完成1个工作。

只需更改您的配置文件:

:verbose: false
:pidfile: ./tmp/pids/sidekiq.pid
:logfile: ./log/sidekiq.log
:concurrency: 1 # Change Here
:queues:
  - ["queue1", 1]
  - ["queue2", 1]
  - ["queue3", 1]
  - ["queue4", 1]
  - ["queue5", 1]
  - critical
  - default
  - low
max_retries: 1

答案 4 :(得分:0)

我认为it您想要一个feature

将其添加到您的工人班级

class YourWorker
  include Sidekiq::Worker
  sidekiq_options queue: :queue1

但是有一个警告,工人只能按队列1排队。

答案 5 :(得分:0)

您可以使用sidekiq-limit_fetch对sidekiq使用高级选项。要限制单个队列的并发性,可以执行以下操作。

第1步。在您的Gemfile中添加gem 'sidekiq-limit_fetch'

步骤2。为sidekiq.yml中的每个队列添加限制

:limits: queue1: 1 queue2: 1 queue3: 1 queue4: 1

答案 6 :(得分:0)

首先在术语上稍作修改。 “工人”是不断运行的线程,它们消耗“队列”中的“作业”。因此,您无需处理worker1,而是worker1将处理queue1中的作业。

现在要解决:-

看来,您的用例是您不希望在给定的瞬间对多个以上的工作人员执行特定类型的工作(在您的情况下是上载到s3的工作)。

要实现这一目标,您将需要一个作业级别的锁定机制。 Sidekiq本身不提供锁定,因此您需要使用外部gem。

我已经使用基于redis的“ sidekiq-lock”在我的项目中实现了类似的目的。

Gem Link

用法如下:-

class Worker
  include Sidekiq::Worker
  include Sidekiq::Lock::Worker

  # static lock that expires after one second
  sidekiq_options lock: { timeout: 1000, name: 'unique-lock-name' }

  def perform
    # your code to upload to s3
  end
end

这将确保您的代码一次只在一个工作者上运行给定作业的一个实例。