APSchedulerで少し進んだジョブスケジューリング
理由と目的と動機
- cronで10分に一回くらいのジョブを回すのが限界に来てしまった。
- __前の処理が10分以上掛かると多重起動になってしまうから。__これを防止したい。
- 何らかの ロック機構 を使えば・・・と思ったのだが、それをジョブのコード中に入れるのは避けたい。
- そのジョブが対象となるロック機構依存になってめんどくさい。
- テストが大変でバグの元。
- 起動しているのはpythonのジョブなので、できればpythonで書かれているものはないのか・・・
多重起動を防止できるジョブスケジューラ探し
- APShcedulerがあった!
- pythonで実装されてる。
- 多重起動を防止できる。
- 多重起動の許可と幾つまでOKかも指定できる。
- cronライクなジョブスケジューリング可能。
- atコマンドの様に指定の時間に一回の起動も可能。
- cronより細かい、秒単位のジョブスケジューリングもできる。
- 本家のドキュメントはこちら
インストール
pipかeasy_installで。
$ easy_install apscheduler
または
$ pip install apscheduler
ジョブスケジューラを書いてみる
- インターバルの秒数を指定して起動するタイプのスケジューラを実装してみる。
import apscheduler.scheduler as ApSched
def job_function():
print "Hello World"
sched = ApSched.Scheduler(standalone=True,coalesce=True)
sched.add_interval_job(job_function, seconds=10)
sched.start()
standaloneオプションはデフォルトFalse。Trueにするとスケジューラ自身がdaemonicに動く。
試しにipythonで実行してみた結果。
In [18]: 2013-11-26 16:12:32.680493
Hello World
In [18]: 2013-11-26 16:12:42.680962
Hello World
In [18]: 2013-11-26 16:12:52.680975
Hello World
尚、ちゃんとプログラムの実行時間を抜いてインターバル時間を計算してくれている。
多重起動防止の実験
from apscheduler.scheduler import Scheduler
import datetime
import time
def job_function_13sec():
print datetime.datetime.today()
time.sleep(13)
print "Hello World"
sched = Scheduler(standalone=True,coalesce=True)
sched.add_interval_job(job_function_13sec, seconds=10)
sched.start()
結果。
In [46]: sched.start()
2013-11-26 16:36:10.818178
WARNING:apscheduler.scheduler:Execution of job "job_function_13sec (trigger: interval[0:00:10], next run at: 2013-11-26 16:36:30.817553)" skipped: maximum number of running instances reached (1)
Hello World
2013-11-26 16:36:30.818776
WARNING:apscheduler.scheduler:Execution of job "job_function_13sec (trigger: interval[0:00:10], next run at: 2013-11-26 16:36:40.817553)" skipped: maximum number of running instances reached (1)
Hello World
2013-11-26 16:36:50.818992
WARNING:apscheduler.scheduler:Execution of job "job_function_13sec (trigger: interval[0:00:10], next run at: 2013-11-26 16:37:10.817553)" skipped: maximum number of running instances reached (1)
Hello World
2013-11-26 16:37:10.818815
WARNING:apscheduler.scheduler:Execution of job "job_function_13sec (trigger: interval[0:00:10], next run at: 2013-11-26 16:37:30.817553)" skipped: maximum number of running instances reached (1)
Hello World
2013-11-26 16:37:30.818828
ジョブのオプションとして デフォルトでmax_runが1 なので、多重起動を防止してくれている。
その後
- cronの様に常時動かすためにsupervisordでデーモン化しました。
- プロセスが死んでも自動再起動でご安心。
- しかしクラッシュしたらメールを飛ばすようにしたい・・・。うーあー。イベントリスナーとかの機能で行けそう。