oinume journal

Scratchpad of what I learned

Better Heroku Schedulerを探したらCustom clock processesにたどり着いた

これは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を試してみた。

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を使おう!