これはHeroku Advent Calendar 2016の11日目の記事です。
HerokuではHeroku Schedulerというcronのようなサービスがあるのですが、使い込むうちに「Daily, Hourly, Every 10 minutesの単位でしかジョブを動かせない」という制限がつらくなってきたので、より良い代替であるCustom clock processesを試してみたという話。
Custom clock processesとは?
clockというプロセスを立ち上げっぱなしにして、そのプロセス内でスケジューリングされたジョブを実行する仕組み。Heroku Schedulerは実行される時だけプロセスが立ち上がるけど、clockの場合は常にプロセスが常駐する。
各言語のScheduler
HerokuのCustom clock processesのドキュメントで触れられているのはJavaとPythonの2種類だけど、各言語ごとにだいたいcron likeなSchedulerが用意されている。今回は自分が慣れているPythonのAPSchedulerを試してみた。
- Java: quartz
- Python: APScheduler
- Ruby: clockwork
- Node.js: node-cron
- Perl: Schedule::Cron
APSchedulerの設定
まずPythonのモジュールのインストールのために、requirements.txt
というファイルを用意する。
echo APScheduler > requirements.txt
次にProcfileに以下を追記する。
clock: python clock.py
ここで指定されているclock.py
がジョブの設定が書かれたファイルになる。どのように記述するべきか、詳しくは公式のドキュメントに書かれている。以下は1分毎にhello world
を出力する設定。
from apscheduler.schedulers.blocking import BlockingScheduler import subprocess scheduler = BlockingScheduler() @scheduler.scheduled_job('interval', minutes=1) def timed_job(): print("Run notifier") subprocess.run("hello world", shell=True, check=True) scheduler.start()
最後に、APSchedulerを動かすのにはPythonが必要なので、buildpackを追加。
heroku buildpacks:add https://github.com/heroku/heroku-buildpack-python
あとはclock.pyをコミットしてディプロイすればOK。
ローカルで試したい場合
ローカルで試してみたい場合は以下のようにAPSchedulerをインストールして、clock.pyを直接呼び出せばOK。
pip install -r requirements.txt python ./clock.py
Custom clock processesとFree Dyno Hours
Heroku Schedulerは実行する際にプロセスが起動されて、プロセスが動いていた時間だけ無料分のFree Dyno Hoursを消費するのだけど、custom clock processesはworkerのようにclockプロセスが常駐する形になるので、起動していた時間分だけFree Dyno Hoursを消費するようなので注意が必要。webと併用していると倍速でFree Dyno Hoursを消費するので気をつけましょう。
まとめ
Heroku Schedulerよりきめ細かい時限式のジョブを定義したいときはCustom clock processesを使おう!