HerokuでRedis


  • 以前の記事(MacでRedis)で作ったプログラムをherokuで動かしてみます。
  • heroku自体は利用できることを前提としてます。

プログラム構成

  • tree コマンドの結果はこんな感じです。
  • virtualenvの環境も一緒にはいってます。
.
├── Procfile
├── __pycache__
├── app.py
├── bin
├── include
├── lib
├── pip-selfcheck.json
├── requirements.txt
└── runtime.txt

requirements.txt

  • 必要なライブラリを記述してます。
  • pip freeze > requirements.txtでできます。
  • 具体的には、下記のようになってます。
click==6.7
Flask==0.12.2
gunicorn==19.7.1
itsdangerous==0.24
Jinja2==2.9.6
MarkupSafe==1.0
redis==2.10.5
Werkzeug==0.12.2

runtime.txt

  • 稼働させるpythonのバージョンを記述します。
  • 具体的には、下記のようになってます。
python-3.6.0

Procfile

  • herokuのwebサーバはgunicornを使用するので設定ファイルを記述します。
  • 具体的には、下記のようになってます。
  • app.pyなので、app:appてなっちゃうのでわかりずらいですねw
web: gunicorn app:app --log-file -

Heroku Redis

注意!

  • herokuの無料コースで試せますが、redisを使うためには認証のためにクレカの登録が必要です。
  • redisのプラグインも無料コースを選べます。

プラグインの設定

  • heroku cliを使います。Webのコンソールでもできます。
% heroku plugins:install heroku-redis                                                                                Installing plugin heroku-redis... done
  • プラグインを追加するとredisが使えるようになってます。
% heroku config -a APP_NAME
=== APP_NAME Config Vars
LANG:      ja_JP.utf8
REDIS_URL: redis://h:pc16fb4fb5781c56263fe9b8ac2〜〜〜2980da@ec2-34-〜〜〜.compute-1.amazonaws.com:9289
TZ:        Asia/Tokyo
  • LANGとTZは別に設定しました。REDIS_URLという環境変数がポイントですね。

ソースコード

  • 環境変数がなければデフォルト値でローカルマシンにも対応するようにしてます。
app.py
import os
import sys
import redis
import random
from flask import Flask
from datetime import datetime as dt

app = Flask(__name__)

# 接続パス、環境変数にあればそれ優先
REDIS_URL = os.environ.get('REDIS_URL') if os.environ.get(
    'REDIS_URL') != None else 'redis://localhost:6379'
# データベースの指定
DATABASE_INDEX = 1  # 0じゃなくあえて1
# コネクションプールから1つ取得
pool = redis.ConnectionPool.from_url(REDIS_URL, db=DATABASE_INDEX)
# コネクションを利用
r = redis.StrictRedis(connection_pool=pool)

@app.route('/')
def root():
    return '{"status":"OK"}'

@app.route('/get')
def get():
    n = random.randrange(len(r.keys()))
    key = r.keys()[n]
    return str(r.get(key))

@app.route('/set')
def set():
    tdatetime = dt.now()
    key = tdatetime.strftime('%Y-%m-%d %H:%M:%S')
    r.set(key, {'val': key})
    return '{"action":"set"}'

if __name__ == '__main__':
    app.run(threaded=True)