Rock Book

history | grep `future`

AWS Lambda でHeroku の無料枠でサーバーが寝ないようにする(2018年版)

先日、ラップボットのDJ マルコをご紹介しました。

masaki925.hatenablog.com

DJ マルコはheroku にデプロイしてるんですが、下記のような問題がありました。

  • フロント(Rails on Heroku) とバック(Flask on Heroku) の2台構成になっている
  • heroku サーバーは30分リクエストが無いと寝てしまうので、ただでさえ起動が遅いのに加えて、フロントがバックの起動を待っている間にタイムアウトして、必ず1リクエスト目がエラーになってしまっていた

そのため、定期的にping して起こしておきたいと思いました。 少し調べたところ、下記の記事が見つかりました。

casualdevelopers.com

UptimeRobot は設定が非常に簡単で良かったのですが、監視の時間帯を設定することができないようでした。

そうすると、24時間 2つのdyno が動き続けることになり、合計で24 * 2 * 30 = 1440 時間となってしまい、無料枠の1000時間を超えてしまう問題がありました。

他の案も、dyno 時間を消費してしまうので、今回の要件には合わなそうでした。

そこで、AWS Lambda でhealth check だけするfunction を作って、AWS Watch Rules で昼間だけ動くようにしました

  • lambda_handler.py
from urllib.request import urlopen
from datetime import datetime, timedelta

def validate(expected, res):
    return expected in str(res)

def lambda_handler(event, context):
    try:
        if not validate(event['expected'], urlopen(event['site']).read()):
            raise Exception('Validation failed')
    except:
        print('Check failed!')
        raise
    else:
        print('Check passed!')
        return 'OK'
    finally:
        print('Check complete at {}'.format(str(datetime.utcnow() + timedelta(hours=9))))

ping 対象のURL と、チェック文言を起動時の引数で与えるようにしているので、他のURL でも流用が可能です。

今回は

{"site": "https://rhyme-bot.herokuapp.com/health/marco", "expected": "OK"}       

AWS Watch Rules に設定しています

f:id:masaki925_8107:20181225152808p:plain

これで、9時〜24時の15時間だけ起こしておくことになったので、15 * 2 * 30 = 900 時間で、無料枠(1000時間) に無事収まります。やったね!