ruby on rails中sidekiq的使用

sidekiq使用redis来保存所有的job和操作数据,所以sidekiq依赖于redis,并且sidekiq默认会去连位于localhost:6379的redis服务器,但是生产环境中可能需要自定义地址

前提:安装并启动redis,不同机器对应的安装方式可自行百度,mac下安装redis可通过

brew install redis

1. 配置redis

配置sidekiq所依赖的redis位置,必须同时定义sidekiq的server和client
config/initializers/sidekiq.rb

# 这里的地址和端口号(1643)都需要配置成正确的
Sidekiq.configure_server do |config|
  config.redis = { url: 'redis://redis.wdxtub.com:1643/12' } #标准格式 config.redis = { url: "redis://#{redis_server}:#{redis_port}/#{redis_db_num}", namespace: redis_namespace }
end
Sidekiq.configure_client do |config|
  config.redis = { url: 'redis://redis.wdxtub.com:1643/12' } #标准格式 config.redis = { url: "redis://#{redis_server}:#{redis_port}/#{redis_db_num}", namespace: redis_namespace }
end

如果要使用 UNIX socket,URL 应该类似于 unix://#{Rails.root}/tmp/sockets/redis.sock

2. 配置文件

配置config/sidekiq.yml文件,一般只有在需要配置高级选项的时候才需要配置这个文件(如果不使用这个名字,可以使用-c指定 sidekiq -c config/name.yml)

:verbose: false
:concurrency: 5 # 并发数
:pidfile: ./tmp/pids/sidekiq.pid
:logfile: ./log/sidekiq.log # 输出的日志地址
:timeout: 30
:queues:
  - default # 写在队列参数中的, 表示让 sidekiq 处理这个 queue
  - [HardWorker, 2] # 使用数组的形式写, 第一个参数为打开的 queue 的名称, 第二个为优先级
  - [EmailWorker, 3]
  - [PasswordWorker, 4]

development:
:concurrency: 5
staging:
:concurrency: 10
production:
:concurrency: 5

3. gemfile中添加对应的包

gem 'sidekiq', '4.0.1', :require => false

4. 在app/jobs文件下新建一个job,来处理异步请求(可以使用命令也可以手动创建)

rails g job add_lots_of_users
#rails g sidekiq:worker Hard # will create app/workers/hard_worker.rb #在app/workers文件下新建一个worker,来处理异步请求(可以使用命令也可以手动创建)

文件中会生成如下内容

class AddLotsOfUsersJob < ActiveJob::Base
  queue_as :default

  def perform(*args)
    # Do something later
  end
end

#class HardWorker
  #include Sidekiq::Worker
  #def perform(name, count)
    # do something
  #end
#end

将耗时的程序写到perform里

def perform(*args)
 # Do something later
 sleep 10
 1000.times do |index|
   user = User.new
   user.name = "atpking#{index}"
   user.save
 end
end

5. 在需要的地方controller或者model中调用,调用示例如下

注意:perform是一个实例方法,但是在调用的时候是用类调用

AddLotsOfUsersJob.perform_later #常规异步执行
AddLotsOfUsersJob.set( wait: 20.minutes ).perform_later #指定延迟多久执行
@users = User.all
#HardWorker.perform_async('bob', 5) #常规异步执行
#HardWorker.perform_in(5.minutes, 'bob', 5) #延迟执行
#User.delay.do_some_stuff(current_user.id, 20) # 也可以通过 delay 来新建任务

6. 在config/application.rb中指定active_job的adapter

adapter默认使用的adapter是Active Job Inline需要指定为sidekiq才支持异步(如果是使用worker这一步可以省略)

config.active_job.queue_adapter = :sidekiq

7. 在rails项目的根目录启动sidekiq

bundle exec sidekiq -d -C config/sidekiq.yml #-d是指后台运行 -c指定配置文件,默认sidekiq.yml文件

另外由于sidekiq的进程并不是非常稳定,可定会自己断掉,所以可以配合监控工具Monit(可以监控任何进程,只需要设定启动和重开的方式即可)使用,详情还请自行百度

8. sidekiq web可视化(这个步骤是可选的)

  1. 添加gem

gemfile添加sinatra

gem 'sinatra', '2.0.0.beta2',require: false

执行

bundle install

tips:
之前直接添加gem 'sinatra'运行时导致报错,google之后判断可能是由于sinatra gem的版本问题,导致运行时报错,修正后的sinatra gem 的为gem 'sinatra', '2.0.0.beta2',require: false

error

  1. 设置路由

routes.rb添加

  require 'sidekiq/web'
  mount Sidekiq::Web => '/sidekiq'
  1. 打开sidekiq web页面

打开Sidekiq web界面,检查该作业是否被处理,浏览器中输入

#port为项目实际启动的端口号
http://localhost:port/sidekiq
sidekiq web页面

为了使Sidekiq有更好的体验需要遵循的一些原则

(以下纯属翻译)

1.让每个 job 的参数小而简单

从前面我们知道,Sidekiq 会把 perform_async 函数的参数保存在 Redis 中,而常见的错误做法是这样的:
quote = Quote.find(quote_id)
SomeWorker.perform_async(quote)
这有什么问题呢?问题很大!把整个 quote 对象都保存在 Redis 中了,而且由于操作是通过异步队列来完成的,很可能在执行到这句话时,quote 本身都改变了,所以我们尽可能让每个 job 的参数小而简单,比方说可以改成像这样
SomeWorker.perform_async(quote_id)
另外除了数据本身可能改变这个问题外,还有序列化和反序列化的问题。Sidekiq 使用 JSON.dump 和 JSON.load 来完成存取操作,所以如果不是简单的 JSON 数据类型,在这一步很可能出错。

2.让每个 job 满足幂等性和事务性

幂等性保证了任务可以执行很多次,不会出现结果不一致的情况;事务性则是保证了结果不因为在 job 执行半路出现问题。我们唯一能做的假设是 Sidekiq 至少会执行每个 job 一次。

3.拥抱并发

Sidekiq 是为并发设计的,所以在设计任务时一定要以并发的想法去思考。如果 Sidekiq 占用流量太高的话,可以考虑用连接池来限制连接数量。

注:本文讲的是Sidekiq结合ActiveJob使用的方式,也可以单独使用Sidekiq Worker
文章中注释掉的是单独使用Sidekiq Worker创建任务跟使用ActiveJob的不同部分

参考
https://github.com/mperham/sidekiq/wiki/Getting-Started
(worker)
https://ihower.tw/rails/background-process.html
(active_job)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容