はじめに
Ruby on Rails (以下Rails) でバックグラウンドジョブを実行する際に一番よく使われているのGemである、Sidekiqのバージョン7.0(以下Sidekiq 7)が2022年10月にリリースされました。
このバージョンでは、管理画面へのメトリクスの追加、Pumaなどのプロセスへの埋め込み、キュー毎の同時実行数を制限するカプセルなど、以前よりも大きな機能追加が行われています。
本記事では、Sidekiqの公式サイトの記事や、GitHubの公式プロジェクトの内容を元に、Sidekiq 7の新機能や変更点の解説を行います。
注意点
本記事で取り扱うエディション
本記事ではGitHubで公開しているOSS版のSidekiqについて記述しています。Pro / Enterprise版を使用している場合は、公式サイト(英語)を参考にしてください。
サポートされるRails / Ruby / Redisのバージョン
サポートされるバージョンは以下の通りになります。
- Ruby on Rails 6.0以上
- Ruby 2.7以上
- Redis 6.2以上
上記より古いバージョンを使用している場合は、アップグレードを事前に行う必要があります。
また、Redisとの接続で使用しているGemがredis
からredis-client
になったり、redis-namespace
が削除されるなど、Sidekiqが依存するGemも変更になっているので、十分な動作確認を行う必要があります。
新機能
管理画面へのメトリクスの追加
ジョブの実行情報を詳細に表示するメトリクスが、Webの管理画面に追加されました。
以下の情報が、過去1時間のグラフとともに表示されます。
- Name: ジョブ名(Jobで終わるクラスの名前)
- Success: 成功ジョブ数(正常終了したジョブ数)
- Failure: 失敗ジョブ数(例外を発生して異常終了したジョブ数)
- Total Execution Time: 総実行時間(ジョブの実行時間の合計)
- Average Execution Time: 平均実行時間(1つのジョブあたり実行時間の平均)
メトリクス自体は簡易的なもので、DataDogなどのフル機能のAPMを置き換えるものではないものの、Sidekiqだけである程度のジョブの実行時間などの情報を視覚的に知ることができるようになっています。
メトリクスの機能の詳細に関しては、以下の公式の記事を確認してください。
参考
Metrics · mperham/sidekiq Wiki
https://github.com/mperham/sidekiq/wiki/Metrics
Pumaなどのプロセスへの埋め込み
これまでSidekiqは、PumaなどのWebサーバーとは別のプロセスと動いていましたが、Webサーバーのプロセス内で動かすことが可能になりました。
埋め込みの利点としては、デプロイが単純になる(設定を行なって、Webサーバーだけをデプロイすれば、Sidekiqも動く)ことと、メモリ消費が少なくなる(Webサーバー側でメモリに読み込んだRubyとRailsのコードやデータをSidekiq側でも使用できる)ことが挙げられます。
埋め込みの欠点としては、WebサーバーとSidekiqが1つのプロセスになっており、また、1つのCPUコアで1つのプロセスを実行することになるので、その中で同時に実行可能なスレッド数が限られていることが挙げられます。
上記の利点と欠点から、小規模なシステムの場合に向いている機能といえるでしょう。
実際にPumaにSidekiqを埋め込む場合は、以下のように設定を行います。(config/sidekiq.yml
での設定はできません。)
# config/puma.rb
workers 2
threads 1, 3
require "sidekiq"
preload_app!
x = nil
on_worker_boot do
x = Sidekiq.configure_embed do |config|
config.queues = %w[default low]
config.concurrency = 2
end
x.run
end
on_worker_shutdown do
x&.stop
end
参考
Embedding · mperham/sidekiq Wiki
https://github.com/mperham/sidekiq/wiki/Embedding
カプセル
ジョブをどのキューからいくつの同時実行数で実行するかを、カプセル(capsule)によって定義することができるようになりました。
以下の設定例では、default
キューにあるジョブは同時実行数5、low
キューにあるジョブは同時実行数3で実行します。これに加え、unsafe
キューは同時実行数1にして、スレッド安全でないジョブを1スレッドで実行するようにしています。
Sidekiq.configure_server do |config|
# defaultカプセル
config.queues = %w[default]
config.concurrency = 5
# lowカプセル
config.capsule("low") do |cap|
cap.queues = %w[low]
cap.concurrency = 3
end
# unsafeカプセル
config.capsule("unsafe") do |cap|
cap.queues = %w[unsafe]
cap.concurrency = 1
end
end
参考
sidekiq/7.0-Upgrade.md at main · mperham/sidekiq
https://github.com/mperham/sidekiq/blob/main/docs/7.0-Upgrade.md
変更点
Strict Argumentで、デフォルトでは例外を発生させるように
Sidekiqのバージョン6.4.0では、ジョブの引数が厳密なJSONになっていることを検証する、Strict Argumentが追加され、引数が不正な場合は警告を出力するようになっていましたが、Sidekiq 7ではこれが厳密化され、例外(ArgumentError
)を発生するようになりました。
この挙動はSidekiq.strict_args!(false)
で無効にしたり、もしくは、Sidekiq.strict_args!(:warn)
で元の警告の挙動に戻すことが可能です。
参考
Implement strict argument checking by kellysutton · Pull Request #5071 · mperham/sidekiq
https://github.com/mperham/sidekiq/pull/5071
サーバー設定の記述方法の変更
Sidekiq 7では、内部的なAPIの実装のリファクタリングが行われた結果、以下の設定の記述方法の変更が行われています。
例: ロガーの設定
# Sidekiq 6
Sidekiq.logger = ...
# Sidekiq 7
# Sidekiq.loggerは使用できなくなった
Sidekiq.configure_server do |cfg|
cfg.logger = ...
end
例: コネクションプールの設定
# Sidekiq 6
POOL1 = ConnectionPool.new(size: 5) { Redis.new(ENV['MY_REDIS_URL']) }
Sidekiq.configure_server do |cfg|
cfg.redis = POOL1
end
# Sidekiq 7
# 直接ConnectionPoolのインスタンスを渡せなくなった
Sidekiq.configure_server do |cfg|
cfg.redis = { url: ENV['MY_REDIS_URL'] }
end
参考
sidekiq/7.0-API-Migration.md at main · mperham/sidekiq
https://github.com/mperham/sidekiq/blob/main/docs/7.0-API-Migration.md
redis-clientへの移行、redis-namespaceの削除
Sidekiqはこれまでredis
Gemを使用していましたが、Sidekiq 7ではRedis 6.0以上のRESP3プロトコルを使用するredis-client
Gemに移行しました。
Railsアプリケーションでは、redis
Gemを引き続き使用できますが、Sidekiq.redis
を使用したRedisとの接続を行う場合は、redis-client
が使用されます。
また、redis-namespace
Gemを使用したRedisのネームスペースのサポートが廃止されました。
この代わりに、Redisが標準で用意している0-15の数字で分けられたデータベースを使用することが推奨されています。
参考
sidekiq/7.0-Upgrade.md at main · mperham/sidekiq
https://github.com/mperham/sidekiq/blob/main/docs/7.0-Upgrade.md
Migrating from redis-namespace | Mike Perham
https://www.mikeperham.com/2017/04/10/migrating-from-redis-namespace/