我在我的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
我想一次为每个队列运行一个唯一的任务。
例如:我在queue1中启动同一个worker 3次,我想处理worker1然后是worker2然后是worker3。
我在sidekiq.yml中添加了带有队列名称的“1”(例如[“queue1”,1])。我以为这个配置只会在queue1中运行一个worker。但那并没有发生。
如何在sidekiq中实现上述配置?
Sidekiq明确地不允许你想做什么。
https://github.com/mperham/sidekiq/wiki/Best-Practices#3-embrace-concurrency
只需使用内置的ActiveJob,因为它听起来像你想要FIFO队列。 Sidekiq用于幂等并发背景
queues
设置控制对队列进行检查的频率,以控制其与其他队列相关的优先级,而不是将并行作业限制在该队列中。
你也可以使用有限数量的线程来启动多个工作者(这就是sidekiq文档为这种情况所建议的),但是当大多数工作人员闲置时,这对于许多负载较低的队列来说可能不实用。
要限制一个工作人员中的特定队列并行作业 - 您可以使用gem sidekiq-limit_fetch和设置,如:
:limits:
queue1: 1
queue2: 1
您可以使用sidekiq-limit_fetch为sidekiq使用高级选项。要限制单个队列的并发性,可以执行以下操作。
步骤1.在Gemfile中添加gem 'sidekiq-limit_fetch'
步骤2.为sidekiq.yml中的每个队列添加限制
:limits:
queue1: 1
queue2: 1
queue3: 1
queue4: 1
首先是术语的略微修正。 “工人”不断运行线程,消耗“队列”中的“工作”。因此,您不处理worker1,而是worker1将处理来自queue1的作业。
现在来解决方案: -
您的用例似乎是您不希望特定类型的作业(在您的情况下上传到s3的作业)在给定时刻在多个工作程序上执行。
要实现这一点,您需要在作业级别使用锁定机制。 Sidekiq本身不提供锁定,因此您需要使用外部宝石。
我使用基于redis的'sidekiq-lock'在我的项目中实现了类似的功能。
用法如下: -
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
这将确保您的代码一次只在一个worker上运行一个给定作业的实例。
Set your Sidekiq concurrency到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