日本語のバックグラウンド処理の記事は、HerokuでRailsを使う人が多いのか、Rubyが中心です。
Pythonの記事も欲しいな〜と思ったので、自分のメモを含めて記録を残しておきます。
そもそも、なぜバックグラウンドで処理させるの?
Herokuでは、普通のHTTPアクセスの場合はweb dyno
さんが捌いてくれるのですが(参考 Dynos and the Dyno Manager)、
web dyno
さんは30秒でタイムアウトになってしまいます。
普通に考えたら、webの処理で30秒かかるって相当重い処理だったり時間がかかる特殊な処理なのかなと思います。
しかしながら、そんな処理をしたい場合もあると思います。
いざ、実装
HerokuのdevcenterにきちんとRuby以外の言語についても、
Worker Dynos, Background Jobs and Queueingに書いてありました。
ここでは、Pythonについて書きます。
言っておきますが、ほぼここのままです。
準備
####1.Redisのインストール
$ brew install redis #ローカルで開発しないなら入れなくてよい
$ pip install redis
####2.RQ(Redis Queue)をインストール
$ pip install rq
####3.必要なライブラリを記載
$ pip freeze > requirements.txt
####4.バックグラウンド処理を呼び出してくれるやつを作る。
こいつが、redisに貯まった仕事を1つずつ呼び出してくれるみたい。
import os
import redis
from rq import Worker, Queue, Connection
listen = ['high', 'default', 'low']
redis_url = os.getenv('REDISTOGO_URL', 'redis://localhost:6379')
conn = redis.from_url(redis_url)
if __name__ == '__main__':
with Connection(conn):
worker = Worker(map(Queue, listen))
worker.work()
####5.バックグラウンドでさせたい処理を書く
from rq import Queue
from worker import conn
from bottle import route, run
q = Queue(connection=conn)
@route('/index')
def index():
result = q.enqueue(background_process, '引数1')
return result
def background_process(name):
# ここに時間のかかる処理を書く
return name * 10
run(host="0.0.0.0", port=int(os.environ.get("PORT", 5000)))
####6.Procfileにworker.pyを記述する
web:python main.py
worker:python worker.py
####7.herokuのアドオンにredistogoを追加する
$ heroku addons:create redistogo
####8.デプロイする
$ git add .
$ git commit -m "add worker"
$ git push heroku master
####9.ワーカーを起動させる
$ heroku scale worker=1
##お疲れ様です、手順は完了です
ここまでくれば、きちんとバックグラウンド処理が動くと思います。
あと、ローカル環境にちゃんとredisのサーバーを入れておくと、main.pyとworker.pyをちゃんと起動しておけば、バックグラウンド処理が動くのの確認ができます。
##困ったときは
ログを見て解決しましょう。
$ heroku logs -t -p worker