EnsekiTT Blog

EnsekiTTが書くブログです。

GWでノージョブ時間が長かったので、Heroku上のWebアプリからCeleryにジョブキューを投げた話

つまりなにしたの?

HerokuにホスティングしたFlaskウェブアプリから
Herokuに同じくホスティングしているCeleryにジョブキューを発行した。

(2dyno構成が必要になるので立ち上げっぱなしにするとHerokuの無料枠を半月で使い切るので注意)

できたもの

github.com
ここのHerokuボタンから実行できますが、2つ目のDynoは起動されないのでManageAppから立ち上げて上げる必要があります。
f:id:ensekitt:20170507141821p:plain

たまに動いているやつ。
JobQueue
(ログを見ないとキューが処理されていることが確認できない残念仕様)

環境:

用意したもの

  • 普通っぽい小規模アプリ
  • キューを受け取って仕事をするワーカー
  • Herokuに必要な諸々
  • gitに必要な諸々
普通っぽい小規模アプリ

web.py

from flask import Flask, render_template, redirect, url_for, flash
import optparse
from worker import task

app = Flask(__name__)
app.config['SECRET_KEY'] = 'Set your own key'

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/add')
def add():
    task.delay("World.")
    flash(u"Add job queue!!")
    return redirect(url_for('index'))

if __name__ == '__main__':
    default_port = 5000

    parser = optparse.OptionParser()
    parser.add_option("-P", "--port",
                      help="Port for the Flask app " + \
                           "[default {0}]".format(default_port),
                      default=default_port)
    parser.add_option("-d", "--debug",
                      action="store_true", dest="debug",
                      help=optparse.SUPPRESS_HELP)
    options, _ = parser.parse_args()
    app.run(debug=options.debug,
            port=int(options.port))

static/
画像などをおいておく
template/
テンプレートになるHTMLをおいておく。
ここにキューを発行するボタンを設置した。

キューを受け取って仕事をするワーカー

worker.py

from celery import Celery
import time
import os
app = Celery('tasks', broker=os.environ['REDIS_URL'],
                      result_backend=os.environ['REDIS_URL'])
#app = Celery('tasks', broker='redis://localhost:6379/0')

@app.task
def task(message):
    time.sleep(10) #時間のかかるタスクのフリをする
    return "Hello {0}".format(message)

こないだ作ったものをそのまま流用

Herokuに必要な諸々

Procfile
requirements.txt
runtime.txt
AddonsでRedisを設定したり

gitに必要な諸々

.gitignore

動作確認

Herokuボタンからデプロイ

Manage AppからWorkerのDynoを起動する
f:id:ensekitt:20170507141734p:plain
こんな状態になる。

立ち上げたアプリにアクセスする。

Add Queueボタンを押す

HerokuのApplication Logsで動作確認

2017-05-07T04:50:35.741138+00:00 heroku[router]: at=info method=GET path="/add" host=enseki-jobqueue.herokuapp.com request_id=94ff4c15-3402-4007-883b-66396f34e275 fwd="60.237.40.77" dyno=web.1 connect=0ms service=140ms status=302 bytes=566 protocol=https
2017-05-07T04:50:35.742021+00:00 app[worker.1]: [2017-05-07 04:50:35,741: INFO/MainProcess] Received task: worker.task[ef85e090-0970-4eba-86c8-3c1ec23f0417]  
2017-05-07T04:50:35.933169+00:00 heroku[router]: at=info method=GET path="/" host=enseki-jobqueue.herokuapp.com request_id=44132473-990b-4e31-8cbc-f2a27c67bb75 fwd="60.237.40.77" dyno=web.1 connect=1ms service=5ms status=200 bytes=2264 protocol=https
2017-05-07T04:50:45.755906+00:00 app[worker.1]: [2017-05-07 04:50:45,753: INFO/PoolWorker-4] Task worker.task[ef85e090-0970-4eba-86c8-3c1ec23f0417] succeeded in 10.00839263992384s: 'Hello World.'

約10秒後にHello Worldと表示されています。
できました。

クリエイティブ・コモンズ・ライセンス
この 作品 は クリエイティブ・コモンズ 表示 4.0 国際 ライセンスの下に提供されています。