Heroku Scheduler
この記事の英語版に更新があります。ご覧の翻訳には含まれていない変更点があるかもしれません。
最終更新日 2023年02月06日(月)
Scheduler は、従来のサーバー環境での cron
と同様に、アプリ上でジョブを定期的な時間間隔で実行するための無料のアドオンです。
Scheduler は無料のアドオンですが、毎月の使用量のカウントに入る One-off dyno を使用して定期的なジョブを実行します。
Scheduler のジョブ実行が予測されますが、保証はされません。Scheduler は、場合によっては、定期的なジョブを実行し損ねることが知られています (ただし、めったに発生しません)。定期的なジョブがアプリケーションの重要なコンポーネントである場合は、信頼性、制御性、可視性を向上させるために、代わりにカスタムクロックプロセスを実行することをお勧めします。
そのインターフェースにアクセスしたら、ダッシュボードを使用して、指定された時間に (10 分ごとに、1 時間ごとに、または毎日) 実行されるようにジョブを設定できます。 起動されると、これらのジョブは One-off dyno として実行され、ログには scheduler.X
などの名前が付けられた dyno として表示されます。
アドオンのインストール
CLI の使用
$ heroku addons:create scheduler:standard
ダッシュボードの使用
アプリのダッシュボードの 「Resources」 (リソース) タブに移動します。「Add-ons」 (アドオン) 検索ボックスで「Heroku Scheduler」を検索します。プロンプトに従ってアドオンをプロビジョニングします。
dyno 時間のコスト
Scheduler は、その月の使用量のカウントに入る One-off dyno を実行します。Scheduler タスクの dyno 時間は、heroku run
またはスケーリングされた dyno の時間と同様にカウントされます。これらは、Heroku の請求書には “スケジューラー” の dyno タイプで表示されます。
タスクの定義
タスクは、アプリケーションで実行できる任意のコマンドです。
Rails の場合は、規則として rake
タスクを設定します。Rails で定期的なタスクを作成するには、次のコードを lib/tasks/scheduler.rake
にコピーし、それをニーズに合わせてカスタマイズします。
desc "This task is called by the Heroku scheduler add-on"
task :update_feed => :environment do
puts "Updating feed..."
NewsFeed.update
puts "done."
end
task :send_reminders => :environment do
User.send_reminders
end
他のフレームワークまたは言語上に構築されたアプリの場合は、別の規則として、タスクを実行する bin/ にスクリプトを追加します。bin/clean-sessions
スクリプトの例を次に示します。
#!/usr/bin/env ruby
require "sequel"
DB = Sequel.connect ENV["DATABASE_URL"]
puts "Cleaning old sessions..."
DB["DELETE FROM sessions WHERE last_seen_at < ?", Time.now - 24*60*60]
puts "done."
タスクのテスト
タスクを記述し、それがローカルで機能していることを確認したら、次のステップとしてアプリケーションをデプロイし、Heroku でタスクをテストします。それを行うには、heroku run
を使用して Heroku でタスクを実行します。
$ heroku run rake update_feed
スケジューラーでは、heroku run
でジョブを実行するために使用されるのと同じ One-off dyno を使用するため、それが heroku run
で動作すれば、スケジューラーからも動作することが保証されます。
ジョブのスケジューリング
ジョブの頻度と時間をスケジュールするには、[My Apps] (マイアプリ) でアプリを見つけて 「General Info」 (一般的な情報) をクリックし、「Add-ons」 (アドオン) ドロップダウンから [Scheduler] を選択することによって Scheduler ダッシュボードを開きます。 このダッシュボードは、次のコマンドから開くこともできます。
$ heroku addons:open scheduler
Scheduler ダッシュボードで、「Add Job…」 (ジョブの追加…) をクリックしてタスクを入力し、頻度、dyno サイズ、次の実行時間を選択します。
毎日のジョブでの次の実行時間は UTC 形式であることに注意してください。特定のローカル時刻でジョブをスケジュールする場合は、適切な UTC オフセットを追加します。
たとえば、rake update_feed
を追加し、「Hourly」 (毎時) と [:30] を選択して、毎時 30 分にフィードを更新します。次に、rake send_reminders
を追加し、「Daily」 (毎日) と [00:00] を選択して、毎日午前 0:00 にリマインダを送信します。
コマンドを指定する代わりに、プロセスタイプを指定することもできます。 それにより、そのプロセスタイプに関連付けられたコマンドが、指定した任意のパラメータと共に実行されます。 詳細は、One-off dyno の構文を参照してください。
出力の検査
定期的なジョブのログは、プロセス scheduler.X
としてログに記録されます。
$ heroku logs --ps scheduler.1
2011-02-04T14:10:16-08:00 heroku[scheduler.1]: State changed from created to starting
2011-02-04T14:10:16-08:00 app[scheduler.1]: Starting process with command `bin/clean_sessions`
2011-02-04T14:10:19-08:00 app[scheduler.1]: Deleting stale sessions...
2011-02-04T14:10:27-08:00 app[scheduler.1]: done.
2011-02-04T14:10:28-08:00 heroku[scheduler.1]: State changed from up to complete
heroku ps
コマンドでは、定期的な dyno も表示されます。
$ heroku ps
=== scheduler: `bin/clean_sessions`
scheduler.1: complete for 5m
=== web: `bundle exec thin start -p $PORT -e production`
web.1: idle for 3h
実行時間の長いジョブ
定期的なジョブは、実行時間の短いタスクを実行するか、またはより実行時間の長いタスクをバックグラウンドジョブのキューに入れるように考慮されています。完了するまでに数分以上かかるジョブはすべて、Worker dyno を使用して実行する必要があります。
スケジューラーによって起動された dyno は、そのスケジューリング間隔より長くは実行されません。たとえば、10 分ごとに実行されるジョブの場合は、約 10 分実行された後に dyno が終了されます。
dyno の終了のスケジューリングには多少変動があることに注意してください。つまり、同じジョブを実行する 2 つの dyno は、新しい dyno が起動されたときに短時間だけ重複する可能性があります。
既知の問題と代替手段
Scheduler は無料のアドオンである
Scheduler は無料のアドオンであり、ジョブがその予定時間に実行されることも、またはまったく実行されないことも保証されません。
- 非常にまれな場合として、ジョブがスキップされることがあります。
- 非常にまれな場合として、ジョブが 2 回実行されることがあります。
Heroku Scheduler と Container Registry
デプロイ方法として Heroku Scheduler と Container Registry を使用している場合は、タスクに web
イメージからアクセスできる必要があります。 タスク実行のために Web 以外のイメージを指定する方法はありません。
Heroku Scheduler の代替手段
Heroku Scheduler の代替手段として、独自のカスタムクロックプロセスの実行があります。これにより、プロセススケジューリングに対する制御と可視性が大幅に向上するため、定期的なジョブが重要なコンポーネントである本番のデプロイメントに推奨されます。詳細は、この記事を参照してください。
Elements Marketplace の dyno のカテゴリには、ユーザーの代わりにタスクをスケジュールし、プロセスを実行するためのいくつかのアドオンソリューションがあります。