はじめに
業務の中で非同期処理を行いたいタスクがあり、システムにsidekiqを新しく導入することで実装しました。
改めて復習も兼ねて記事を書くことにしました。
実装
sidekiq用のサーバーを構築
sidekiq:
uild:
context: .
dockerfile: Dockerfile
volumes:
- .:/app
env_file:
- .env
ports:
- 3000:3000
command: bundle exec sidekiq -C config/sidekiq.yml
GemFileにsidekiq追加し、bundle install実行
gem 'sidekiq'
sidekiqの各種設定
1. アダプターをSidekiqにする
ActiveJobをsidekiqと連携させる。
config.active_job.queue_adapter = :sidekiq
2. sidekiqの設定ファイルを追加する
:queues:
- test_job
- default
キューの実行に優先順位をつけることも可能。(数字の大きい順に優先的に処理されるようになる。)
:queues:
- ['test_job', 2]
- ['default', 1]
設定できる項目一覧
-
max_retries
リトライ回数を指定(デフォルト25回)-
retry: 0
リトライしない。ジョブがデッド状態になり、sidekiqのダッシュボード画面から再試行が可能。 -
retry: false
リトライしない。画面から再試行ができなくなる。(メール送信処理など複数回行われてはいけない処理に対して設定すると良い)
-
-
verbose
trueにするとより詳細なログ情報を提供される(デフォルトfalse
) -
pidfile
プロセスID(PID)を格納するファイルのパスを指定する -
logfile
Sidekiqのログファイルを格納するパスを指定する -
concurrency
同時に処理されるジョブの数(1つのsidekiqプロセスで使用するスレッド数)を設定する(デフォルト25) -
queues
sidekiqが処理を行うキュー名を指定。ここで指定されたキュー以外のジョブは処理されない。 -
timeout
ジョブのタイムアウト時間(秒)。数字で指定。
3. sidekiqから接続するRedisのURLを設定
環境変数REDIS_URL
は.env
などで定義する。
Sidekiq.configure_server do |config|
config.redis = { url: ENV["REDIS_URL"] }
end
Sidekiq.configure_client do |config|
config.redis = { url: ENV["REDIS_URL"] }
end
4. 非同期処理を行うメソッドを定義する
class SamplemJob < ApplicationJob
queue_as :sb_auto_exam
sidekiq_options retry: 2, backtrace: 20
sidekiq_retry_in do |count|
10
end
def perform
p 'test'
end
end
queue_as
ジョブのキュー名を指定。sidekiq_optionsの方でも設定できるが、こちらで設定するケースが多い印象
sidekiq_retry_in
ジョブがリトライされるまでの待機時間を指定。デフォルトだと(4 ** n(リトライ回数)) + (rand(30) * (n + 1))
sidekiq_optionsでジョブごとに個別にsidekiqの設定ができる。
設定できる項目一覧
-
retry
リトライ回数を指定する -
queue
ジョブのキュー名を指定する -
backtrace
falseにするとエラーが発生した場合にバックトレースを保存しない。数字を指定するとバックトレースの行数を指定
4. メソッドを実行する
# 非同期で実行する
SamplemJob.perform_later
# 同期で実行する
SamplemJob.perform_now
# 3分待ってから実行される
SamplemJob.perform_in(3.minutes)
# 2025年1月1日の午前0時0分0秒にジョブを実行する
SamplemJob.perform_at(DateTime.new(2025, 1, 1, 0, 0, 0))
5. sidekiqのダッシュボードを表示するようにする
require 'sidekiq/web'
mount Sidekiq::Web, at: "/sidekiq"
上記の例なら/sidekiq
でアクセスできます。
補足
sidekiqで非同期でジョブを実行する場合、ジョブのキュー名(queue_as
もしくはsidekiq_options
で設定)とsidekiqが処理するキュー名(config/sidekiq.yml
で設定)を同じにする必要があります。
異なっていた場合、sidekiqが処理を行わず、ジョブがどんどん貯まるだけになってしまうので要注意
参考
https://zenn.dev/overflow_offers/articles/20230130-how-to-use-sidekiq
https://www.cyberowl.co.jp/blog/technology/3589
https://serip39.hatenablog.com/entry/2020/12/28/235800
https://qiita.com/ryohashimoto/items/69dac29a63f682143df7
https://zenn.dev/ivry/articles/637f6f0f0c7db7