定期的なジョブとカスタムクロックプロセス
この記事の英語版に更新があります。ご覧の翻訳には含まれていない変更点があるかもしれません。
最終更新日 2022年01月27日(木)
Table of Contents
多くのアプリでは、予定時間にジョブを実行する必要があります。たとえば、アプリがリモート API を 5 分ごとにポーリングしたり、メールレポートを毎日午前 0:00 に送信したりする必要がある場合があります。このユースケースには一般に cron ツールが使用されますが、これは Heroku などの水平方向に拡張可能な環境には適していません。より強力で、かつ柔軟な解決策がジョブスケジューラーです。
より要件の緩いユースケースについては、「単純なジョブスケジューリング」のセクションを参照してください。
ジョブスケジューラーはプロセスモデルを使用して、指定された間隔で起動し、実行される作業をスケジュールする軽量のシングルトンプロセスを実行します。バックグラウンドワーカー と組み合わされると、ジョブスケジューリングへのクリーンで、拡張可能なアプローチを形成します。
概要
ジョブのスケジューリングとそのジョブの実行は、それぞれ独立したタスクです。ジョブの実行をそのスケジューリングから分離すると、各コンポーネントの責任が明確に定義されるようになるため、より維持可能なシステムが生成されます。
バックグラウンドジョブを実行するのではなく、キューに入れるには、ジョブスケジューラーのみを使用します。バックグラウンドワーカーがその後、キューに入れられたジョブを独自に受け取って実行します。
スケジューリングと実行のコンポーネントを分離することにより、要求を満たすためのバックグラウンドワーカーの数を容易にスケーリングできます。簡略化するために、可能な場合は、1 つのプロセスを超えてジョブスケジューラーをスケーリングしないでください。そうでない場合は、複雑なロックのロジックを実装しない限り、重複した作業をスケジュールすることもできます。
単純なジョブスケジューリング
単純なスケジューリング要件 (非常に大まかな間隔 (毎日、毎時、または 10 分ごと) でタスクを実行するなど) を持つアプリは、Scheduler アドオンをジョブスケジューラーとして使用できます。この無料のツールは通常、単純な繰り返しのジョブには十分です。
より具体的な実行間隔 (1 日に 3 回、2 時間ごと、場合によっては 5 秒ごとなど) を定義するアプリは、代わりに、カスタムクロックプロセスを実装してジョブをスケジュールする必要があります。
カスタムクロックプロセス
クロックプロセスには、カスタムスケジュールを指定する機能以上に、プロセスモデルの一部として定義される (他の論理アプリケーションコンポーネントと一貫している) という追加のメリットがあります。これによりテストが簡略化され、外部の依存関係が削減されるほか、開発と本番の間の環境の同等性が向上します。
カスタムクロックプロセスの定義
カスタムクロックの実装は、言語によって大きく異なります。ただし、アプリケーションのプロセスモデルの一部として、クロックプロセスの定義は非常に簡単です。標準的な Node.js アプリケーションの Procfile
を次に示します。
web: node web.js
worker: node worker.js
clock: node clock.js
概念的に、clock.js
の内容は実体がありません。重要なのは、clock.js
プロセスが、どのようなジョブをどのような間隔で実行するかの判定と、これらのジョブをバックグラウンドで実行するためのスケジューリングにのみ責任を負っていることです。
そして、worker.js
で定義されたバックグラウンドワーカーは、定期的な作業を受け取り、それをただちに実行することに責任を負っています。
Heroku でのクロックプロセス
前に説明したように、クロックコンポーネントは、重複したジョブのスケジューリングや複雑なロックのロジックの必要性を回避するためにシングルトンプロセスである必要があります。Heroku にデプロイされた clock
プロセスを、単純に 1 つの dyno にスケーリングします。
$ heroku ps:scale clock=1
Scaling 'clock' processes... done, now running 1
ジョブをスケジュールする適切な時間を見極めるために、clock
プロセスはスケールアップしたまま稼働している必要があります。ジョブをスケジュールするときだけでなく、実行中の clock
プロセスがある限り、dyno では請求時間が発生し続けます。
定期的なジョブの処理が大幅に増加した場合は、worker
プロセスに追加の dyno が必要になる可能性があります。定期的なジョブを受け取って実行するために、少なくとも 1 つの worker
dyno が実行される必要があります。
dyno は少なくとも 1 日に 1 回再起動されるため、dyno の再起動中にジョブ間隔がスキップされないようにするには、クロックプロセスの起動時に何らかのロジックが存在する必要があります。
実装
アプリケーションで定期的なジョブを実装できるライブラリやサービスは多く存在します。さまざまな言語での定期的なジョブの実装の具体的な例には、以下のものがあります。
言語/フレームワーク | チュートリアル |
---|---|
Python | |
Java |