🤸‍♂️

Sidekiqをカチャカチャいじってみた

2023/01/31に公開

◎前提:検証のためローカルでカチャカチャいじってみただけなので、雑多ですいません。。。

Rails+Redis+Sidekiqの関連図

この図がとてもわかりやすかった

https://dev.icare.jpn.com/dev_cat/sidekiq/

事前準備

ローカルで試す場合こちらを参考に作った

https://qiita.com/yumiyon/items/6835d90e621e73268021

Workerの実装

非同期処理を行うクラスは Sidekiq::Workerを include してつくります。あとは perform メソッドの中に非同期で行いたい処理を書くだけです。引数は自由に追加して OK です。

リトライ回数を5回に設定している

Sidekiq::Workerをincludeしている

class TestWorker < ApplicationController
  include Sidekiq::Worker
  sidekiq_options queue: :test, retry: 5

  def perform(name)
    puts 'work: ' + name
  end

end

コントローラーにperform_asyncを定義。これが非同期で処理されるジョブです

perform_asyncを使っている(csv出力のジョブなどで)

class HomesController < ApplicationController
  def show
    TestWorker.perform_async('Hello world')
  end
end

以下のgemをインストールした

gem 'sidekiq'
gem 'sinatra', require: false # ダッシュボードを利用するため
gem 'sidekiq-failures' #失敗の処理を管理画面でみれる
gem 'sidekiq-history' #履歴(失敗や成功したジョブ)を管理画面でみれる
gem 'sidekiq-statistic' #ステータスを管理画面でみれる

※redisのgemはデフォルトで入っているが、redisをbrewなどでインストールする必要がある

諸々起動する

  • rails起動
  • redis起動
  • sidekiq起動

管理画面

http://localhost:3000/sidekiq

ジョブを実行する

この Worker は以下のように呼び出します。

TestWorker.perform_async('Hello world')
% rails c
Loading development environment (Rails 7.0.4)
irb(main):001:0> TestWorker.perform_async('Hello world')
2022-12-15T00:04:10.322Z pid=9840 tid=abc INFO: Sidekiq 7.0.2 connecting to Redis with options {:url=>"redis://localhost:6379", :size=>5, :pool_name=>"internal"}
=> "d3fd4c306b8032880ef9eb67"

sidekiqを見てみる

puts 'work: Hello world'が呼ばれている

管理画面を見てみる

実行前

完了が11

実行後

完了が12で正常に実行されているのがわかる

失敗になる理由

エラーなどでジョブの実行が正常にされなかった時

失敗の数だけ、失敗タブの数が増えます。

待機状態になる理由

sidekiqのプロセスが停止している(sidekiqが起動していない)状態で、ジョブが実行される。そして、redisの中にジョブが積まれている状態になり「待機状態」になる。

(今回のメール送信されない障害はメモリ使用量圧迫によるOMM killerで、sidekiqのプロセスが切られていたことによるもので、結果待機状態にメールのジョブが溜まっていた)

sidekiqをコントロールCで切る

=プロセスが消える

ジョブを実行

TestWorker.perform_async('Hello world')

実行したジョブ(testというキューの中のジョブ)が待機状態になる

(redisの中にジョブが積み上がる)

再度、sidekiqを起動する

→プロセスが立ち上がる

→待機状態のものが再試行にいく→それをまた再試行する→成功にはならない(成功になってほしいのだがならない、、、)

再試行になる理由

ジョブの実行が失敗時に再試行になる

例)

この Worker は以下のように呼び出します。引数を2つ指定してます

TestWorker.perform_async('Hello world', 1)

sidekiqを見てみる

引数が足りないエラーが起きています

管理画面

再試行に1がついている

testのキューにさっき実行した失敗したジョブとエラーメッセージが表示される

再試行を実行する

前提、ジョブの実行に失敗したのが再試行に入るので

管理画面から「今すぐ再試行」しても失敗する(=失敗のカウントが増える)

(もしかしたら方法はあるのかもしれない)

デッドになる理由

リトライ回数(再試行の回数)のMAX(デフォルトのリトライ回数は25回)を達したらデッドに移行する

さっきの失敗したジョブはリトライ5回に設定したので5回を超えるとデッドに移動される

死亡タスクは,sidekiqのダッシュボードからのみ再試行をかけることができる(でも、エラーで死亡しているので再試行しても実行されないはず)

予定になる理由

(例)perform_inメソッドで引数に時間を指定するとsidekiqのキューの「予定」に入ってから1分後にジョブが実行される(どのような時に使うのかわからない)

TestWorker.perform_in(1.minutes, 'Hello world')

予定が1増えている

予定の中(さっき実行したジョブが入っている)

参考

https://github.com/mperham/sidekiq

Discussion