寝ても覚めてもこんぴうた

プログラム書いたり、ネットワーク設計したり、サーバ構築したり、車いじったり、ゲームしたり。そんなひとにわたしはなりたい。 投げ銭は kyash_id : chidakiyo マデ

Appengineで初回1回だけ実行したい(設定の初期化)ときはwarmupを利用する

Appengine (GAE) はリクエストのイベントでインスタンスが起動されるので、通常のアプリケーションを実装した際に初回1回だけ実行する処理というのが普通に実装するとなかなか難しい。
特にDB(Datastore)アクセスなどが必要な場合にはrequestが無いとappengineのcontextを作成することができないのでそもそもDB(Datastore)へのアクセスができない。

そんなときに利用するのがwarmupリクエスト。

warmupリクエストとは

最初に書いたとおりでappengineはリクエスト駆動で動くため、warmupのリクエストがappengineの環境から実行される。
appengineはよしなにスケールするため、スピンアップのタイミングでそのリクエストがそのインスタンスに対して、1度だけやってくるというイメージ。

設定方法

app.yamlへwarmupの設定を追加する

Github にサンプルファイルをおいているが、以下のようにwarmupを実行するという設定を入力する必要がある。

ポイントは2箇所

まずは、warmupリクエストを使用しますよ。という設定が以下。

inbound_services:
- warmup

もう一つは、warmupリクエストは /_ah/warmup のパスへリクエストが送られるため、

- url: /_ah/warmup
  script: _go_app
  login: admin

という設定が必要となる。
_ah ってどういう意味?って思うかもしれないが、 app handler とかって意味とどこかで見たけど忘れたw
また、 login:admin と書かれている場合には外部からのアクセスが行えないため、外からいたずらされないためには忘れずに付けましょう。

Application側の設定

こちらも Githug にサンプルを置いていますが、
特に難しいことはなく、handlerの設定として

http.HandleFunc("/_ah/warmup", warmup)

のような実装を行い、warmup functionの中で初期化を行いたい処理を書くと良いです。
先程も書いたように通常のハンドラと同様に実装できますので、requestを使ってappengine contextの生成も問題なく行えます。

参考

公式ドキュメント

追記 : 落とし穴

warmupはどうやら絶対に実行してもらえるという感じのものでもないらしい。

Note that warmup requests are not guaranteed to be called. In some situations loading requests are sent instead: for example, if the instance is the first one being started up, or if there is a steep ramp-up in traffic. However, there will be a "best effort" attempt to send requests to already warmed-up instances if warmup requests are enabled

意訳 : warmupの実行は保証してないよー、ベストエフォートだよー

つまり、warmupが実行される前にリクエストを受け取った際には、初期化がされているか判別して初期化する、のような制御が必要

こちらの資料の p.12 - p.13 あたりに特に詳しく説明が載っています。(ありがたい)

www.slideshare.net

enjoy GAE/go!