Sidekiq Rails 4.2使用Active Job还是Worker?有什么区别?

52

这是我第一次异步处理作业,我正在实现Sidekiq来进行应用程序的后台处理。我将使用它来发送提醒电子邮件和应用程序通知。我对于是否应该使用Active Job创建发送电子邮件的作业还是使用Sidekiq Worker发送电子邮件感到困惑。它们似乎做着相同的事情,而Rails 4.2 Active Job似乎很新……它是否替代了使用Sidekiq Worker的需要?

下面是使用Active Job作业和Sidekiq Worker发送邮件的相同代码。我正在使用Whenever gem进行调度。

my_mailers.rb

class MyMailers < ActionMailer::Base

  def some_mailer(r.user_id)
    @user = User.find(r.user_id)
    mailer_name = "ROUNDUP"
    @email = @user.email
    @subject ="subject text"
    mail(to: @email, 
      subject: @subject,  
      template_path: '/notifer_mailers', 
      template_name: 'hourly_roundup.html',
      )
  end
end

使用 Sidekiq "Worker"
some_worker.rb

class SomeWorker
  include Sidekiq::Worker

  def perform()
    @user = User.all
    @reminders = @user.reminders.select(:user_id).uniq.newmade
    @reminders.each do |r|
      MyMailers.some_mailer(r.user_id).deliver_later
    end
  end

end

使用Active Job的“Job”
some_job.rb

class SomeJob < ActiveJob::Base
  queue_as :mailer

  def perform()
    @user = User.all
    @reminders = @user.reminders.select(:user_id).uniq.newmade
    @reminders.each do |r|
      MyMailers.some_mailer(r.user_id).deliver_later
    end
  end

end

我的 Whenever 调度程序中的两个示例 schedule.rb

require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
set :path, Rails.root
set :output, Rails.root.join('log', 'cron.log')

#using a worker
every 1.day, :at => '4:30 am' do
  runner SomeWorker.perform_async
end

#using a job
every 1.day, :at => '4:30 am' do
  runner SomeJob.perform_async
end
4个回答

89

简短回答是它们是同一物,ActiveJob 称之为 Job,而 Sidekiq 称之为 Worker。我决定保持术语不同,以便人们可以区分两者。

你可以使用任意一个。请注意,ActiveJob 并未提供对完整的 Sidekiq 选项集的访问权限,因此,如果您想要自定义作业的选项,您可能需要将其创建为一个 Worker。


谢谢您的回答和出色的工作!还有一个非常相关的问题:是否仍然可以在邮件程序中使用旧的Sidekiq语法?例如:UserMailer.delay.welcome_email(@user.id) - superuseroi
当然。所有“旧”的API仍然可以使用,并且非常好用。 - Mike Perham
太好了,这是允许Sidekiq提供其强大的重试功能的绝佳方式 :) 这很有用。❤ - superuseroi
2
幸运的是,自从sidekiq 6.0版本以后,也可以通过ActiveJob传递sidekiq_options :) https://github.com/mperham/sidekiq/blob/master/6.0-Upgrade.md#whats-new - loybert
我的团队最近就我们是否将我们的Sidekiq类称为Worker还是Job进行了一场辩论。作为一个老派人士,我指出了这个答案,并坚持使用Worker,但最终我还是选择了团队对Job的偏好。今天,我在发现@MikePerham本人在这里推荐使用Job之后,完全支持这个决定:https://www.mikeperham.com/2021/11/07/whats-new-in-sidekiq-6.3/ - David Hempy

30

Rails 4.2 新增了 ActiveJob 来统一作业 API,但要异步运行它,您需要一个后台处理程序,这就是 sidekiq 的作用。

Sidekiq 已经有其自己的 worker 类,但它也实现了新的 active job 类,所以可以两种方式都工作。

然而,使用 active job 的好处在于您可以更改后台处理程序,而无需更改代码,只要它们都支持您想要的功能(例如:在特定时间处理作业;具有多个优先级队列)。

这里有一个Rails API指南,其中包含支持active job的处理程序的良好比较,包括每个处理程序支持的功能。如果您懒得查看链接,这是比较表:

|                   | Async | Queues | Delayed   | Priorities | Timeout | Retries |
|-------------------|-------|--------|-----------|------------|---------|---------|
| Backburner        | Yes   | Yes    | Yes       | Yes        | Job     | Global  |
| Delayed Job       | Yes   | Yes    | Yes       | Job        | Global  | Global  |
| Qu                | Yes   | Yes    | No        | No         | No      | Global  |
| Que               | Yes   | Yes    | Yes       | Job        | No      | Job     |
| queue_classic     | Yes   | Yes    | No*       | No         | No      | No      |
| Resque            | Yes   | Yes    | Yes (Gem) | Queue      | Global  | Yes     |
| Sidekiq           | Yes   | Yes    | Yes       | Queue      | No      | Job     |
| Sneakers          | Yes   | Yes    | No        | Queue      | Queue   | No      |
| Sucker Punch      | Yes   | Yes    | No        | No         | No      | No      |
| Active Job Inline | No    | Yes    | N/A       | N/A        | N/A     | N/A     |
| Active Job        | Yes   | Yes    | Yes       | No         | No      | No      |

看起来即使你使用了ActiveJob并将其设置为Sidekiq,它仍然属于Sidekiq的能力范畴,对吧?(因为我的重试目前仍在进行中) - dtc

8

我建议使用原生的Sidekiq,因为它具有更多的功能。我偶尔会遇到一些与ActiveJob相关的奇怪序列化问题。尽管ActiveJob追求统一的API目标,但正是出于这个原因,它限制了许多实现方式,而且在目前来看并没有太多的好处。就个人而言,如果我决定要交换实现方式以获得更丰富的功能集,我很愿意在未来的某个时候(可能永远不会发生,您不会仅仅因为好玩而交换应用程序的关键部分,比如activerecord vs mongodb),付出重新编写代码的“可能”代价。


1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接