你必須很努力

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

2020/09/30
字數統計: 1.1k閱讀時間: 5 min

前言

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

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

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

如何安裝

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

1
2
3
4
# Gemfile
gem 'sidekiq', '~> 6.1', '>= 6.1.2'

# 記得要 bundle

加上 Web 介面,可參考此 commit

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

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

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

1
2
3
4
5
6
7
8
9
10
# config/application.rb
config.active_job.queue_adapter = :sidekiq


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

寫個 Worker 確認能否執行

可參考此 commit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 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]

如何執行

終端機輸入

1
2
3
sidekiq
# or
bundle exec sidekiq

Sidekiq 啟動成功畫面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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 官方文件

1
2
3
4
# Gemfile
gem 'sidekiq-scheduler', '~> 3.0', '>= 3.0.1'

# 記得要 bundle

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 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 畫面

更多指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
sidekiq -h

INFO: 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

參考資料

  1. RailsCasts - #366 Sidekiq
  2. 在 Rails 專案中使用 Sidekiq 處理非同步任務
  3. Sidekiq 如何處理非同步任務

小結

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/

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

原文連結:https://riverye.com/2020/09/30/Day25-Ruby-on-Rails-中的-Sidekiq-的介紹與應用/

發表日期:2020-09-30

更新日期:2020-09-30

CATALOG
  1. 1. 前言
  2. 2. 如何安裝
  3. 3. 寫個 Worker 確認能否執行
  4. 4. 如何執行
    1. 4.0.1. Sidekiq 啟動成功畫面
    2. 4.0.2. Sidekiq Web 介面
  • 5. 指定時間執行 Sidekiq
    1. 5.0.1. Sidekiq Recurring Jobs 畫面
    2. 5.0.2. 更多指令
  • 6. 參考資料
  • 7. 小結