sidekiq在ruby on rails中的使用

1,300 阅读3分钟

Sidekiq介绍

Sidekiq是什么

Sidekiq 是一个多线程的后台任务处理框架。在Web请求中,有很多任务是可以放到后台执行的,比如网购商品,就可以直接向用户购买成功,相应的物流通知等就可以放到后台任务去做,不用在购买的同时立即执行,这些任务也称作异步任务。

Sidekiq基本概念

Job

在 Sidekiq 中的 Job 指的是某一个任务的一次执行, 注意与我们通常意义上说 “一个 Job” 指的是一类 Job.(一类任务)

Worker

因为 Sidekiq 是使用 Celluoid 来完成其多线程的控制的, 而 Celluoid 是 Ruby 中的多线程模式 Actor 模式的实现, 所以在 Sidekiq 中的 Worker 我们以拟人的方式去理解. 我拥有一个工人, 不过有一点要区分的是这些 Worker 都是按照”操作手册”在执行任务, 所以他不会被限制在某一类任务上.

Queue

队列的意义在于区分任务并且让任务排队, Sidekiq 中将每一类的任务使用一个 Queue 来区分开.

具有类似异步功能的框架还有哪些?

Resque、Delayed Job、BackgroundJob,更多的可以参考Rails Guide Active Job

异步任务的基本原理

web操作可以看作是生产者,将需要处理的任务放入队列,sidekiq等异步任务组件是队列的消费者。

Sidekiq在Rails项目中的安装使用

Sidekiq 安装

环境 ruby 2.7.4,rails 6, 在Gemfile文件中增加下面一行

gem 'sidekiq'

然后执行bundle install,配合sidekiq主要是使用redis数据库, 在这里我们使用redis,安装过程不在此展开。

基本配置和使用

配置文件

在rails 项目下增加配置文件config/sidekiq.yml,内容如下

# 并发线程数量
:concurrency: 5
:pidfile: tmp/pids/sidekiq.pid
:logfile: ./log/sidekiq.log # 输出的日志地址
development:
  :concurrency: 2
production:
  :concurrency: 2
# 监听处理的队列
:queues:
  - critical
  - default
  - [mailers,2]  # 前面是队列名,后面是队列优先级,数字大优先级高
  - low
  - low_priority

无需额外配置,sidekiq会默认去链接redis

启动

执行下面的命令启动

sidekiq -C config/sidekiq.yml -e development # 加 -d 后台运行

截屏2023-02-26 下午5.44.33.png

这样我们就成功启动了sidekiq,可以看到我们没有配置redis,在图片的倒数2、3行可以看见redis的连接信息。

使用

 rails g sidekiq:job MySidekiq 

sidekiq 6.3.0以后用Sidekiq::Job替代Sidekiq::Worker, 执行完后会在app/sidekiq/目录下生成my_sidekiq_job.rb文件,如下

my_sidekiq_job.rb

在rails console 中执行

结果

这样我们就成功启动的sidekiq服务,并正常使用

自定义配置项

我们在config/initializers/目录下新建一个文件sidekiq.rb,

sidekiq.rbconfig/目录下新建redis.yml

redis.yml

更多的配置信息可以在这查看

结合Active Job 一起使用

配置适配器

config/application.rb文件中增加如下代码

 # 全局适配器
 config.active_job.queue_adapter = :sidekiq

也可以在单独的文件中指明适配器

class GuestsCleanupJob < ApplicationJob
  self.queue_adapter = :resque
   #....
end
   # 现在,这个作业使用resque作为后端队列适配器
   # 把config.active_job.queue_adapter配置覆盖了  

如何使用

使用rails g job my命令就会在jobs目录下生成my_job.rb

my_job.rb

调用如下

MyJob.set( wait: 10.minutes ).perform_later #指定延迟多久执行

MyJob.set(queue: :another_queue).perform_later(record) #指定队列

active_job中set

在不使用ActiveJob的时候,在perform后面的参数是不能传对象的,使用ActiveJob则是可以的,Active Job 支持参数使用 GlobalID。这样便可以把 Active Record 对象传给作业,而不用传递类和 ID,再自己反序列化。模型类要混入 GlobalID::Identification。Active Record 模型类默认都混入了。

#以前的写法
class UserJob < ApplicationJob
  def perform(user_class, user_id)
    user = user_class.constantize.find(user_id)
    #...
  end
end

#现在可以
class UserJob < ApplicationJob
  def perform(user)
    #...
  end
end

ActiveJob文档

sidekiq web可视化

  1. 设置路由
require 'sidekiq/web'
mount Sidekiq::Web => '/sidekiq-stat'
  1. 启动rails 项目
rails s
  1. 打开网址http://localhost:3000/sidekiq-stat/scheduled

截屏2023-02-26 下午7.19.33.png

  1. 还可以配置账号密码等设置。

扩展

sidekiq-limit_fetch

github.com/brainopia/s…

一种扩展,允许您限制Sidekiq的Server进程中特定队列中的并行数。也可限制sidkiq的进程数。

截屏2023-03-06 下午4.17.40.png