はじめに
Ruby on Rails (以下Rails) でバックグラウンドジョブを実行する際によく使用されるGemである、Sidekiqのバージョン6.0が今年(2019年)9月にリリースされました。このバージョンでは、Active Jobへのオプション指定などの機能強化と共に、パフォーマンス向上が行われ、sidekiqctl
コマンドが廃止されるなどの大きな変更が行われています。本記事では実際に使用した経験を元に、Sidekiq 6の新機能や変更点について説明を行います。
注意点
本記事で取り扱うエディション
本記事ではGitHubで公開しているOSS版のSidekiqについて記述しています。Pro / Enterprise版を使用している場合は、公式サイト(英語)を参考にしてください。
サポートされるRails / Ruby / Redisのバージョン
サポートされるバージョンは以下の通りになります。
- Ruby on Rails 5以上
- Ruby 2.5以上
- Redis 4以上
上記より古いバージョンを使用している場合は、アップグレードを事前に行う必要があります。
新機能
Active JobでSidekiq独自のオプションを指定可能に
ActiveJob::Base
を継承したジョブで使用する際に、sidekiq_options
を指定することで、Sidekiq独自のオプションを一部使用できるようになりました。
以下はリトライの回数と、Web UIで表示するバックトレースの行数をsidekiq_options
で指定しています。
class MyJob < ActiveJob::Base
queue_as :myqueue
sidekiq_options retry: 10, backtrace: 20
def perform(...)
end
end
以下が使用できるオプションの一覧となります。
オプション | 値 | 内容 |
---|---|---|
retry |
整数 | リトライ回数を指定する |
backtrace |
true, false, 整数 | SidekiqのWeb UIにバックトレースを表示するかどうか 整数の場合は指定した行数で表示する |
参考
ログの出力形式を選択可能に
ログの出力機能がプラグイン化され、出力形式を選択できるようになりました。例えば、JSON形式の出力を行う場合は、以下のようにSidekiq::Logger::Formatters::JSON
を指定します。
Sidekiq.configure_server do |config|
config.log_formatter = Sidekiq::Logger::Formatters::JSON.new
end
以下が使用できるログの出力形式の一覧となります。
フォーマッタ | 説明 |
---|---|
Sidekiq::Logger::Formatters::Pretty |
通常の出力 |
Sidekiq::Logger::Formatters::WithoutTimestamp |
タイムスタンプなしで出力 |
Sidekiq::Logger::Formatters::JSON |
JSON形式で出力 |
ログ出力の例
Sidekiq::Logger::Formatters::Pretty
2019-08-31T15:36:07.569Z pid=82859 tid=11cy9br class=HardWorker jid=528f1b0ddc4a9d0690464fe4 INFO: start
Sidekiq::Logger::Formatters::WithoutTimestamp
pid=82859 tid=119pz7z class=HardWorker jid=b7f805c545c78770d30dc1fd elapsed=0.089 INFO: done
``Sidekiq::Logger::Formatters::JSON`
{"ts":"2019-09-01T22:34:59.778Z","pid":90069,"tid":"104v8ph","lvl":"INFO","msg":"Running in ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin17]"}
参考
- Pluggable Log Formatter by Tensho · Pull Request #4093 · mperham/sidekiq
- Logging · mperham/sidekiq Wiki
ジョブ毎のログレベル指定が可能に
ワーカーの.set
メソッドの引数でlog_level
を指定することで、特定のジョブのログの出力レベルを指定できるようになりました。
MyWorker.set(log_level: :debug).perform_async(...)
SidekiqはデフォルトでRubyの標準ライブラリのLoggerを使用しており、log_level
で指定できるのは、:unknown
、:fatal
、:warn
、:info
、:debug
になります。
参考
- Support job-specific log levels by fatkodima · Pull Request #4287 · mperham/sidekiq
- Job-specific log levels · Issue #4286 · mperham/sidekiq
- Logging · mperham/sidekiq Wiki
ジョブのタグ付けが可能に
ワーカーのクラスのsidekiq_options
にtags
を指定することで、ジョブのタグ付けができるようになりました。
class MyWorker
include Sidekiq::Worker
sidekiq_options tags: ['bank-ops', 'alpha']
...
end
参考
- Support job tags by fatkodima · Pull Request #4280 · mperham/sidekiq
- Support for ad-hoc job tags? · Issue #4073 · mperham/sidekiq
Web UIでのダークモードのサポート
ダークモードがサポートされたブラウザ(IEやEdge、Operaは非サポート)でモードが有効な状態でWeb UI(Sidekiqの管理画面)にアクセスした場合は、黒ベースの画面で表示するようになりました。
参考
変更点
sidekiqctl
コマンドの削除
Sidekiqプロセスを停止、終了するために用いられてきた、sidekiqctl
コマンドが廃止されました。Sidekiq 6では、このコマンドの代わりにkill
コマンドでシグナルを送ることで、プロセスの停止、終了を行うことができます。
廃止されたコマンド | 代替となるコマンド | 説明 |
---|---|---|
sidekiqctl quiet |
kill -TSTP <pid> |
ワーカーの各スレッドを停止 |
sidekiqctl stop |
kill -TERM <pid> |
(上記コマンドの実行後に)プロセスを終了 |
デーモン化を廃止し、サービスとして実行するように
サービスの管理をOS側(Systemd、Upstartなど)で行うようにするために、デーモン化を廃止しました。このため、本番環境などサーバーで動かす場合は、Sidekiqのサービスの設定ファイルを新たに作成し、サービスを有効にする必要があります。
デーモン化の廃止に至った背景に関しては、Sidekiq作者による説明が以下のページにあります。
上記の記事では、以前から使用されてきた長時間動作するデーモンプロセスが、現在ではSystemdを使用したサービスに置き換えられていて、このことによって、ロギングやクラッシュ時の再実行などの処理を自前で実装することがなく、より堅牢な実行が可能になった、ということが書かれています。
Sidekiqのサービスの設定、起動や停止コマンドに関しては、この記事の次の節のアップグレードの部分を参考にしてください。
logfile
、pidfile
コマンド引数の廃止
上記のデーモン化の廃止に伴って、ログの出力や、プロセスIDの保持をSystemdなどのサービス側で行うようになったので、sidekiq
コマンドからlogfile
、pidfile
コマンド引数が削除されました。
デフォルトのシャットダウン時間が8秒から25秒に変更に
HerokuのDynoとAmazon ECS コンテナがアプリケーションのシャットダウンで30秒のタイムアウトを使用するようになったため、Sidekiqも8秒から25秒にタイムアウト時間を伸ばしました。以前の挙動に戻すには、オプション-t 8
をsidekiq
コマンドに対して指定します。
REDIS_PROVIDER
環境変数の検証を行うように
REDIS_PROVIDER
環境変数は、RedisサーバーのURLを保持する他の環境変数を指定するのに使用します。もし、REDIS_PROVIDER
変数に直接URLなどの不適切な文字列が指定されている場合は、以下のような警告を出すようになりました。
REDIS_PROVIDER should be set to the name of the variable which contains the Redis URL, not a URL itself.
Platforms like Heroku will sell addons that publish a *_URL variable. You need to tell Sidekiq with REDIS_PROVIDER, e.g.:
参考
パフォーマンスの向上
生成するオブジェクトを減らすなど、細かいコードのチューニングを行うことによって、Sidekiq 5系列と比較して、10-15%実行速度が向上しているそうです。
参考
- Optimize cloning of job payload by fatkodima · Pull Request #4303 · mperham/sidekiq
- Speedup UnitOfWork#queue_name by fatkodima · Pull Request #4299 · mperham/sidekiq
- Reduce allocated objects by fatkodima · Pull Request #4269 · mperham/sidekiq
アップグレード方法
Gemのアップグレード
最初に、Gemfileに以下のように指定して、bundle update
を実行して、Sidekiq 5系列の最新版にアップグレードします。
gem 'sidekiq', '< 6'
Sidekiqを動かしてみて、非推奨の警告(Deprecation warnings)が出ないようにコードの修正を行います。
修正が完了したら、Gemfileに以下のように指定して、再度bundle update
を実行して、Sidekiq 6.xへアップグレードします。
gem 'sidekiq', '< 7'
サービスの設定ファイルの作成
変更点で述べたように、本番環境では、Sidekiqプロセスはデーモンでなくサービスとして起動するようになったため、設定ファイルを作成する必要があります。
開発環境では、これまで通りユーザーがsidekiq
コマンドを実行してフォアグラウンドで起動し、ログは標準出力および標準エラー出力に送信されるため、サービスとして起動させる必要はありません。
SystemdでSidekiqをサービスとして実行するには、以下のファイルを元に設定ファイルを生成し、サーバーの適切な場所(CentOSの場合は/usr/lib/systemd/system、Ubuntuの場合は/lib/systemd/system)に配置する必要があります。
例えばrbenvのbundlerを使用していて、アプリケーションのディレクトリが/var/www/myapp/current
の場合は、以下のように変更する必要があります。
WorkingDirectory=/var/www/myapp/current
...
ExecStart=/usr/local/rbenv/shims/bundle exec sidekiq -e production
ファイルの配置を行ったら、以下のコマンドでサービスを有効にします。
$ sudo systemctl enable sidekiq
サービスの起動と停止
設定ファイルを配置後は、以下のコマンドでサービスの起動と停止を行います。
サーバーの起動
$ sudo systemctl start sidekiq
サーバーの停止
$ sudo systemctl stop sidekiq