Closed9

Sidekiqのタイムアウトについて調べる

たすくんたすくん

ECSにデプロイしている場合は、30 秒のタイムアウトで SIGKILL シグナルを送信するため、安全に Sidekiq をシャットダウンするなら、タイムアウトの秒数を30秒以内に収める必要がある。
そうしないと、実行中のジョブが kill されてしまう可能性がある。

タスクが停止すると、各コンテナのエントリプロセス (通常は PID 1) に SIGTERM シグナルを送信します。タイムアウトが経過すると、今度は SIGKILL シグナルをプロセスに送信します。デフォルトでは、SIGTERM シグナルの送信後 30 秒のタイムアウトで SIGKILL シグナルを送信します。

https://aws.amazon.com/jp/blogs/news/graceful-shutdowns-with-ecs/

たすくんたすくん

ジョブが25秒を超えてしまう場合の対策として

  • 25秒以内に収まるようにジョブの単位を細かく分割する
  • ECSの stopTimeout パラメータの値と、Sidekiq の timeout の値を伸ばす
    • stopTimeout パラメータは最大120秒まで設定できる
たすくんたすくん

Sidekiq でシグナルを受け取る部分のコードを見てみる

エントリポイント

https://github.com/sidekiq/sidekiq/blob/main/bin/sidekiq

シグナルのハンドリング

https://github.com/sidekiq/sidekiq/blob/main/lib/sidekiq/cli.rb#L218-L221

シグナルの挙動

TERM は raise Interrupt で例外を発生させる
TSTP は cli.launcher.quiet を実行する
https://github.com/sidekiq/sidekiq/blob/main/lib/sidekiq/cli.rb#L194-L214

quiet

新規ジョブの実行を停止する
@donetrue にする
https://github.com/sidekiq/sidekiq/blob/main/lib/sidekiq/launcher.rb#L47-L54
https://github.com/sidekiq/sidekiq/blob/main/lib/sidekiq/manager.rb#L43-L49
https://github.com/sidekiq/sidekiq/blob/main/lib/sidekiq/processor.rb#L44-L48

たすくんたすくん

全ての実行中のジョブの完了を待ってから、Sidekiq をシャットダウンする検証

https://n8.hatenablog.com/entry/2015/05/01/100424 を参考に手元でも動かしてみる

スクリプト

# app/jobs/sample_job.rb
class SampleJob
  include Sidekiq::Job

  def perform
    sleep 60
  end
end
# lib/tasks/sample.rake
task sample: :environment do
  SampleJob.perform_async
  puts 'SampleJob enqueued'
  sleep 10

  ps = Sidekiq::ProcessSet.new
  abort 'Sidekiq process not running' if ps.count.zero?

  ps.first.quiet!

  puts "TSTP sent\nWaiting 10sec for status update"
  sleep 10

  while (running_tasks = ps.first['busy']).positive?
    puts "Waiting for tasks to finish. Num tasks: #{running_tasks}"
    sleep 5
  end

  ps.first.stop!
  puts 'SIGTERM sent'
end

ローカルで実行

# ターミナルA
bundle exec sidekiq -C config/sidekiq.yml
# ターミナルB
bin/rake sample

ログ

ターミナルA

Running via Spring preloader in process 71387
SampleJob enqueued
TSTP sent
Waiting 10sec for status update
Waiting for tasks to finish. Num tasks: 1
Waiting for tasks to finish. Num tasks: 1
Waiting for tasks to finish. Num tasks: 1
Waiting for tasks to finish. Num tasks: 1
Waiting for tasks to finish. Num tasks: 1
Waiting for tasks to finish. Num tasks: 1
Waiting for tasks to finish. Num tasks: 1
Waiting for tasks to finish. Num tasks: 1
Waiting for tasks to finish. Num tasks: 1
SIGTERM sent

ターミナルB

2025-03-19T06:06:19.749Z pid=71015 tid=1ns7 class=SampleJob jid=8deb6eaf269ad0a1b70d9070 INFO: start
2025-03-19T06:06:32.931Z pid=71015 tid=1ftb INFO: Received TSTP, no longer accepting new work
2025-03-19T06:06:32.931Z pid=71015 tid=1ftb INFO: Terminating quiet threads
2025-03-19T06:06:32.931Z pid=71015 tid=1ntr INFO: Scheduler exiting...
2025-03-19T06:07:20.340Z pid=71015 tid=1ns7 class=SampleJob jid=8deb6eaf269ad0a1b70d9070 elapsed=60.592 INFO: done
2025-03-19T06:07:28.010Z pid=71015 tid=1ftb INFO: Shutting down
2025-03-19T06:07:28.116Z pid=71015 tid=1ftb INFO: Bye!

ちゃんと全ての実行中のジョブの完了を待ってから、Sidekiq をシャットダウンできている 🎉

このスクラップは2025/03/19にクローズされました