Day25 — Ruby on Rails 中的 Sidekiq 的介紹與應用

被端走的小菜
9 min readSep 29, 2020

--

前言

Sidekiq 是 Ruby on Rails 中蠻常用的後台任務處理系統,上篇介紹了 Resque Gem,已知這 2 套 Gem 相比,Sidekiq 的效能比較好…

本身提供的 API 十分簡潔,連 Source Code 也是易於閱讀 (例如這段),Sidekiq 分成 3 種版本 (開源、專業、企業版),欲知差異可到官方網站往下滑便能看到差異比較表,本文以 OSS (Open Source Software) 進行操作

後續的文章會以此 repo 作為範例

如何安裝

放在 Gemfile 檔案中,可參考此 commit

# Gemfile
gem 'sidekiq', '~> 6.1', '>= 6.1.2'
# 記得要 bundle

加上 Web 介面,可參考此 commit

# config/routes.rb
require 'sidekiq/web'
mount Sidekiq::Web => '/sidekiq'

將 ActiveJob 改由 Sidekiq 處理,可參考此 commit

備註: 預設情況下的佇列 (Queue) 的優先順序都為 1,下方 ['default', 1]['mailers', 1] 可縮寫成 defaultmailers

# config/application.rb
config.active_job.queue_adapter = :sidekiq
# config/sidekiq.yml
:concurrency: 10
:queues:
- ['default', 1]
- ['mailers', 1]
:timeout: 86400

寫個 Worker 確認能否執行

可參考此 commit

# app/controllers/users_controller.rb
Api::CreateOrderWorker.perform_async(@user.id)
# app/worker/api/create_order_worker.rb
module Api
class CreateOrderWorker
include Sidekiq::Worker
sidekiq_options retry: 7, dead: true, queue: 'create_order_worker'
sidekiq_retry_in { |count| count + 86_400 } sidekiq_retries_exhausted do |msg, _ex|
subject = "[Api::CreateOrderWorker]Out of retries! #{msg['class']} with #{msg['args']}"
_message = "error: #{msg['error_message']}"
FileLog.logger('worker/api/create_order_worker.log').error(subject)
# ...
end
def perform(user_id)
logger.info "====== start ====== user_id: #{user_id}"
puts 'hello world'
logger.info '====== done ======'
rescue StandardError => e
logger.error "[Api::CreateOrderWorker] ERROR:\n #{e.inspect}\n #{e.backtrace}"
end
private def logger
FileLog.logger('worker/api/create_order_worker.log')
end
end
end
# config/sidekiq.yml
- ['create_order_worker', 10]

如何執行

終端機輸入

sidekiq
# or
bundle exec sidekiq

Sidekiq 啟動成功畫面

bundle exec sidekiq
m,
`$b
.ss, $$: .,d$
`$$P,d$P' .,md$P"'
,$$$$$b/md$$$P^'
.d$$$$$$/$$$P'
$$^' `"/$$$' ____ _ _ _ _
$: ,$$: / ___|(_) __| | ___| | _(_) __ _
`b :$$ \___ \| |/ _` |/ _ \ |/ / |/ _` |
$$: ___) | | (_| | __/ <| | (_| |
$$ |____/|_|\__,_|\___|_|\_\_|\__, |
.d$$ |_|
2020-09-27T07:58:31.874Z pid=95276 tid=1z4c INFO: Booted Rails 6.0.3.3 application in development environment
2020-09-27T07:58:31.874Z pid=95276 tid=1z4c INFO: Running in ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-darwin19]
2020-09-27T07:58:31.874Z pid=95276 tid=1z4c INFO: See LICENSE and the LGPL-3.0 for licensing details.
2020-09-27T07:58:31.874Z pid=95276 tid=1z4c INFO: Upgrade to Sidekiq Pro for more features and support: https://sidekiq.org
2020-09-27T07:58:31.874Z pid=95276 tid=1z4c INFO: Booting Sidekiq 6.1.2 with redis options {}
2020-09-27T07:58:31.876Z pid=95276 tid=1z4c INFO: Starting processing, hit Ctrl-C to stop

Sidekiq Web 介面

指定時間執行 Sidekiq

需額外安裝擴充套件 sidekiq-scheduler Gem,可參考此 commit

備註: 可參考 sidekiq-scheduler GitHub 官方文件

# Gemfile
gem 'sidekiq-scheduler', '~> 3.0', '>= 3.0.1'
# 記得要 bundle

相關設定及範例如下,可參考此 commit

備註: 對 Cron 不熟悉的話,可看 Wiki 說明,並搭配 Crontab.guru 這網站使用

# config/application.rb
Redis.exists_returns_integer = true
# config/routes.rb
require 'sidekiq-scheduler/web'
# config/sidekiq.yml
- ['scheduler', 5]
:schedule:
CheckWorker:
cron: '30 * * * *'
queue: scheduler
enabled: true


# app/worker/check_worker.rb
class CheckWorker
include Sidekiq::Worker
sidekiq_options retry: 0, queue: 'check_worker'
def perform
puts 'At minute 30.'
end
end
# 這範例是每整點的 30 分,會執行一次 CheckWorker

Sidekiq Recurring Jobs 畫面

更多指令

sidekiq -hINFO: sidekiq [options]
-c, --concurrency INT processor threads to use
-d, --daemon Daemonize process
-e, --environment ENV Application environment
-g, --tag TAG Process tag for procline
-q, --queue QUEUE[,WEIGHT] Queues to process with optional weights
-r, --require [PATH|DIR] Location of Rails application with workers or file to require
-t, --timeout NUM Shutdown timeout
-v, --verbose Print more verbose output
-C, --config PATH path to YAML config file
-L, --logfile PATH path to writable logfile
-P, --pidfile PATH path to pidfile
-V, --version Print version and exit
-h, --help Show help

小結

Sidekiq 功能非常強大且容易上手,工作上蠻常使用,舉例來說,它的 retry 機制很實用,像打 API 建立訂單,若過程中發生錯誤的話,透過 retry 機制,能重新執行該 job (能設定 retry 上限、每次間隔時間、超過 retry 上限的話…),並設定 Slack 與 Email 通知 (這部分要自己實作),能即時知道發生異常,進而判斷要如何處理,本身的 Wiki 文件也很完整,且網路上有許多文章、影片 (ex: Youtube 等) 可以參考

鐵人賽文章連結:https://ithelp.ithome.com.tw/articles/10246607
medium 文章連結:https://link.medium.com/RPXFvaCabab
本文同步發布於 小菜的 Blog https://riverye.com/

備註:之後文章修改更新,以個人部落格為主

--

--

被端走的小菜
被端走的小菜

Written by 被端走的小菜

大家好,我是被端走的小菜。以個人部落格更新為主:https://riverye.com/

No responses yet