今回はタイトル通り、sidekiq pro / enterpriseのwikiを読んだので、忘れないように気になった機能の概要をメモしておきます✍
⚠私が拙い英語力 + 技術力で理解した内容のMEMOです。内容が間違っている可能性があるので、注意してください。⚠
前提事項
整理した内容は、2019/04/30現在のsidekiqのwikiに記載されている内容です。
Home · mperham/sidekiq Wiki · GitHub
sidekiq pro
Batches
https://github.com/mperham/sidekiq/wiki/Batches
Batch
として複数のJob
の実行をまとめられる機能。
※概要は下記のコードを参照
# Batchの作成 batch = Sidekiq::Batch.new # Batchの説明 batch.description = "Batch description (this is optional)" # Callbacks # `:success`: すべてのJobが成功して完了 # `:complete`: いくつかのJobが失敗を含んで完了 batch.on(:success, SomeClass, 'uid' => current_user.id) batch.on(:complete, 'AnotherClass#method', 'uid' => current_user.id) # BatchにJobを登録 # MEMO: Batchは1つ以上のJobを持たなければならない # https://github.com/mperham/sidekiq/wiki/Batches#notes batch.jobs { rows.each { |row| RowWorker.perform_async(row) } } puts "Just started Batch #{batch.bid}" class SomeClass def on_complete(status, options) puts "Uh oh, batch has failures" if status.failures != 0 end def on_success(status, options) puts "#{options['uid']}'s batch succeeded. Kudos!" end end
Sidekiq::Batch.new
でBatchのインスタンスを作成し、Sidekiq::Batch#jobs
のブロック内でWorker.perform_async
を呼び出すことで、BatchにJobを登録することが出来る。
またSidekiq::Batch#on
でsuccess(成功)
、complete(完了※失敗を含む)
した場合のCallbackを登録することが出来る。
下記の例のような複雑なWorkflowを組むことも出来る👀
- https://github.com/mperham/sidekiq/wiki/Complex-Job-Workflows-with-Batches
- https://github.com/mperham/sidekiq/wiki/Really-Complex-Workflows-with-Batches
Reliability
https://github.com/mperham/sidekiq/wiki/Reliability
sidekiqの信頼性を向上される機能。大きく分けて2つの機能が提供される。
super_fetch
: Jobが完了するまでRadisのqueueを削除しない機能、もしもsidekiqのprocessが落ちて再起動した or 前回の走査から1時間経過した場合は、Redisのqueueをフルスキャンし、queueを再実行する。reliable_scheduler
: より信頼性の高いschedule実行機能、Redisからjobをpopして実行してくれる。(sidekiq proではLua
を使って、より信頼性の高いスケジューラ)を提供してくれるらしい。※このへんはよく分かってない・・・。
有効にするためにはinitializers/sidekiq.rb
内で下記を実行する。
Sidekiq::Client.reliable_push! unless Rails.env.test? Sidekiq.configure_server do |config| config.super_fetch! config.reliable_scheduler! end
Client-side Reliability
https://github.com/mperham/sidekiq/wiki/Pro-Reliability-Client
sidekiqのClient側で信頼性を向上させる機能。具体的には、最初にメモリ上のqueueにpushし、RedisへのNetwork接続が確立されてから、Redisへqueueのpushを行う機能。
有効にするためにはinitializers/sidekiq.rb
内で下記を実行する。
Sidekiq::Client.reliable_push! unless Rails.env.test?
Expiring Jobs
https://github.com/mperham/sidekiq/wiki/Pro-Expiring-Jobs
一定期間後に無効化されるJobを作成する機能。
有効にするためにはinitializers/sidekiq.rb
内で下記を実行する。
require 'sidekiq/pro/expiry'
Worker
内で、sidekiq_options expires_in: 1.hour
とするとJobの有効期間を1時間にすることが出来る。(1時間以内に実行されなければ、もう実行しない。)
class SomeWorker include Sidekiq::Worker sidekiq_options expires_in: 1.hour ... end # 実行時に指定する場合 SomeWorker.set(expires_in: 1.day).perform_async(...)
※Batchに含まれているJobがexpiredされた場合は、成功とみなされるため注意する。
sidekiq enterprise
Rolling Restarts
https://github.com/mperham/sidekiq/wiki/Ent-Rolling-Restarts
sidekiqのRolling Restartを行う機能。sidekiqのrolling restartには、einhorn
というprocessマネージャーを使用する。
einhornsh --execute upgrade
がrolling restartのトリガーとなるので、デプロイ後等、プログラムが置き換わったあとに実行するようにする。- 新しいprocessが立ち上がってから10秒後に、まだ古いprocessが起動してたらUSR2を送って古いprocessを正常に終了させてくれる。
Rate Limiting
https://github.com/mperham/sidekiq/wiki/Ent-Rate-Limiting
Jobの実行を制限するような機能を使える。制限はSidekiq::Limiter
を使って追加する。
Concurrent
Jobの同時実行数を制限する機能。Sidekiq::Limiter.concurrent
で制限する。下記例では、同時実行数は50
に制限される。
ERP_LIMIT = Sidekiq::Limiter.concurrent('erp', 50, wait_timeout: 5, lock_timeout: 30) def perform(...) ERP_LIMIT.within_limit do # call ERP end end
Bucket, Window
指定期間内での実行数を制限する機能。Sidekiq::Limiter.bucket
、Sidekiq::Limiter.window
で提供される。
c
# Bucketc # 下記例では、1秒あたりに30回までと実行が制限される def perform(user_id) user_throttle = Sidekiq::Limiter.bucket("stripe-#{user_id}", 30, :second, wait_timeout: 5) user_throttle.within_limit do # call stripe with user's account creds end end # Window # 下記例では、5秒間に1回までになる?Windowはよくわからなかった。。。 def perform(user_id) user_throttle = Sidekiq::Limiter.window("stripe-#{user_id}", 5, :second, wait_timeout: 5) user_throttle.within_limit do # call stripe with user's account creds end end
※bucketとwindowの違いがわからん。。。
Unlimited
既存の制限を外す機能。Sidekiq::Limiter.unlimited
で提供される。
※管理ユーザだけ制限を解除するような用途で使用する。
ERP = Sidekiq::Limiter.concurrent("erp", 10) def perform(...) lmtr = current_user.admin? ? Sidekiq::Limiter.unlimited : ERP lmtr.within_limit do # always executes for admins end end
Periodic Jobs
https://github.com/mperham/sidekiq/wiki/Ent-Periodic-Jobs
Jobの定期実行機能。
initializers/sidekiq.rb
内で下記のようにcrontab形式でスケジュールを定義出来る。※WebUIでも一覧を確認出来る。
Sidekiq.configure_server do |config| config.periodic do |mgr| # see any crontab reference for the first argument # e.g. http://www.adminschoice.com/crontab-quick-reference # or https://crontab.guru/ mgr.register('0 * * * *', SomeHourlyWorkerClass) mgr.register('* * * * *', SomeWorkerClass, retry: 2, queue: 'foo') mgr.register(cron_expression, worker_class, job_options={}) end end
Unique Jobs
一意になるようなJob(Redis内に複数のqueueが存在しないようなJob)を定義することが出来る機能。
有効にするためにはinitializers/sidekiq.rb
内で下記を実行する。
Sidekiq::Enterprise.unique! unless Rails.env.test?
Worker
を下記のように定義すると、10分後または、Jobが正常に処理された際に次回のJobがqueueにpushされる。
class MyWorker include Sidekiq::Worker sidekiq_options unique_for: 10.minutes def perform(...) end end
おわりに
今回はsidekiq proとenterpriseで提供される機能で私が気になったものを整理してみましたm( )m
proのBatchやReliabilityの機能は、プロダクト運用で有用そうなので、ビジネスで利用するときは使うと良さそうな機能ですね👀
enterpriseもRolling RestartsやPeriodic Jobsなど、かゆいところに手が届く機能が多く良さそうに見えました👀
みなさんも気になったら詳しい内容が公式Wikiに記載されてるので、読んでみてくださいー。
Home · mperham/sidekiq Wiki · GitHub
それでは👋