【问题标题】:How to configure to sidekiq queue to run only task at a time如何配置到sidekiq队列一次只运行任务
【发布时间】:2019-04-03 04:33:35
【问题描述】:

我在我的 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 中运行一个工作人员。但这并没有发生。

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

【问题讨论】:

  • 不清楚。您希望您的 3 个工作人员以循环方式从 queue1 中挑选工作(一个工作,另外两个等待)?或者worker1在queue1上工作,worker2在queue2上工作等等?
  • 我的意思是喜欢循环时尚。一个有效,另外两个等待
  • @karan 在这种情况下,为什么不为每个队列设置 1 个工作人员?
  • @MartinZinovsky 这对我来说并不好。我有更多的工人。我想限制每个队列的工作人员。
  • @SergioTulentsev 任何帮助将不胜感激

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


【解决方案1】:

首先对术语进行轻微更正。 “工人”不断运行线程,消耗“队列”中的“作业”。因此,您不处理 worker1,而是 worker1 将处理来自 queue1 的作业。

现在来解决问题:-

您的用例似乎是您不希望特定类型的作业(在您的情况下上传到 s3 的作业)在给定时刻在多个工人身上执行。

要实现这一点,您需要在作业级别设置锁定机制。 Sidekiq 本身不提供锁定,因此您需要使用外部 gems。

我在我的项目中使用了基于 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

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

【讨论】:

    【解决方案2】:

    【讨论】:

      【解决方案3】:

      只需使用内置的ActiveJob,因为听起来您需要 FIFO 队列。 Sidekiq 用于幂等并发后台处理

      【讨论】:

      • 是的,要么您最初的设计很糟糕,现在还欠了技术债务,要么您使用了错误的工具来完成这项工作。也许 RabbitMQ 可能适合你。
      【解决方案4】:

      我认为it 你想要一个feature

      将它添加到您的工人阶级

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

      但有一个警告,工人只能通过 queue1 排队。

      【讨论】:

      • 这正是我们想要的!谢谢!
      【解决方案5】:

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

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

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

      :limits:
        queue1: 1
        queue2: 1
      

      【讨论】:

        【解决方案6】:

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

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

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

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

        【讨论】:

          【解决方案7】:

          Set your Sidekiq concurrency 为 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
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2022-01-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-07-25
            • 1970-01-01
            相关资源
            最近更新 更多