38
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

HerokuAdvent Calendar 2019

Day 15

"初めてのHeroku開発"の前に〜Herokuのクセを理解する〜

Last updated at Posted at 2019-12-14

Herokuのクセとうまく付き合う

こんにちは。
ここ数年、Heroku + Javaでの開発プロジェクトによく参画しています。
いくつかのプロジェクトを通し、Herokuならではクセに直面してきました。
弊社の @yonyonsaeki記事と合わせて、これからHerokuプロジェクトをはじめられる方に向けて、私が知らずにハマったクセ(もしくは地雷)についてご紹介していきます

Web Dynoは60秒以内に起動しないといけない

Web Dynoは起動後の60秒以内で$PORTをlistenしなくてはなりません。
60秒を過ぎてもlisten状態にならない場合、R10 - Boot timeoutとなり、Dynoはクラッシュします。

Web Dynoは30秒以内にレスポンスを返さないとダメ

Web DynoはHTTPリクエストを受信してから30秒以内にレスポンスを返さなければなりません。
30秒を経過すると、Heroku routerによりHTTPコネクションが切断されてしまいます。
レスポンスに時間のかかるAPIなどは注意しましょう。

Dynoは1日ごとに再起動する

Web Dynoは、およそ1日に一回必ず再起動されます。
期限の長いセッション情報などをメモリに持っておくと、再起動でリセットされてしまうためやめておきましょう。
再起動時にダウンタイムはありません。これは、実行中のDynoの他に新しいDynoが新規で起動し、新しいDynoがlisten状態になるまでHeroku routerは古い実行中のDynoにリクエストをルーティングするためです。
2019/12/16 追記
ダウンタイムをなくすためにはPreboot機能の有効化が必要でした。
有効化するには「Heroku の Preboot 機能を深掘りした - Feedforce Developer Blog」を参照してください。
@masutaka さん、ありがとうございます!

ファイルを保存してはいけない

DynoはDockerのコンテナの様なものです。
Dyno内のファイルシステムに作成したファイルは、再起動すると消えてしまいます。
また、Dyno間でファイルを共有できません。複数のWeb Dynoなどを立ち上げていると、web1にはファイルがあるけどweb2にはファイルがない、なんてことが発生します。
ストレージが必要な時はBucketeerの様なHeroku AddonsのData Storesを検討してみましょう。

ログは標準出力に出す

ログはファイルに出力せずに、全て標準出力へ出しましょう。
Heroku CLIでheroku logs --tail --app <App名>と実行すると、リアルタイムのログを見ることができます。
HerokuのダッシュボードからもMore -> View logsで参照できます。
さらに、Papertrailの様なLoggingのHeroku Addonsを利用してみましょう。検索機能がとても便利です。

スケジューラで起動したジョブは、次のスケジュール時間までに終了しないと強制終了される

Heroku Schedulerを利用すると、cron的にコマンドを実行できます。コマンドはOne-off Dynoで実行されます。
スケジューラで実行したOne-off Dynoは、次のスケジュール時刻までに実行しないと強制終了されます。コマンドの最後でDBにコミットする様なケースでは、ロングランして強制終了->ロールバック->次のスケジュールでコマンド実行->ロングラン->強制終了...のループが繰り返されます(やらかしてとても困った)。

他の環境変数を参照する環境変数は設定できない

heroku config:set VAR=valueの様に、Appに対して環境変数を定義できます。
この時にFOO=$BARの様な他の環境変数を参照する定義はできません。
他の環境変数の参照が必要な場合は.profileを追加してみてください。
以下はREDIS_URLをコピーしたSPRING_REDIS_URLを定義する.profileの例です。

export SPRING_REDIS_URL="$REDIS_URL"

Slugサイズは500MBまで

AppはSlugというものにパッケージされます。Slugには構築したアプリの他に依存関係のモジュールなどが含まれます。
DynoはSlugを展開し、起動されます。
このSlugには500MBのサイズ上限があります。
サイズの大きなファイルを利用する場合などは注意してください。
また、Gitのコミット数が多くなり未参照のオブジェクトが増えたり、依存関係のキャッシュで圧迫される様な場合、Heroku CLIのrepoプラグインを利用してゴミ掃除をしてみましょう。

そもそもSlugに含めたくないファイル・フォルダがある場合(Dynoでアプリを実行する際に不要なファイル)は.slugignoreに指定することで、Slugから除外することができるので活用しましょう。
ただし、除外されるタイミングはビルドの前です。ビルド後に生成されるファイルをこの方法では削除できないため注意しましょう。

アクセス元のIPアドレスは X-Forwarded-For ヘッダからとる

Web Dynoから接続元のIPアドレスを取得する時はX-Forwarded-Forヘッダから取得しましょう。
Web DynoはHeroku Routerと呼ばれるリバースプロキシの後ろで実行されています。
そのため、REMOTE_ADDRはHeroku RouterのIPアドレスとなります。

DynoのIPアドレスは固定できない

HerokuはAWS上に構築されており、DynoのIPアドレスはAWSのアドレス範囲のどれかになります。
外部システムとの連携において、IPアドレスの固定化が要求として上がるケースがあります。
HerokuからのアウトバウンドのIPアドレスを固定したい場合は、ProximoなどのAddon利用を検討してください。
※Heroku Private Spacesを利用している場合は例外です。固定のIPアドレスが割り当てられます。

38
27
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
38
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?