2015年6月24日水曜日

GAE、Modulesの設定 ②

前回 の続きです。GAE(Google App Engine)の一機能である Modules APIの設定について、具体的に説明していきます。

GAEのデプロイツールは、従来の APPCFG が GCLOUD に変更になりました。移行方法などは次のリンクの記事を参考にしてください。
→ Google Cloud SDK への移行
yaml 定義ファイルの作成

Moduleを作成するには、そのための yaml ファイルを作成する必要があります。取り敢えず、バックエンド・ジョブ用の例を示します。

back_job.yaml

application: myapp
module: back-job
version: 1-00
api_version: 1

instance_class: B1
basic_scaling:
  max_instances: 2
  idle_timeout: 1m

runtime: python27
threadsafe: true

handlers:
- url: .*
  script: gaehandler.wsgiapp
  login: admin

back_job.yaml ファイルを作成します。GAEのアプリケーション情報を記述する app.yaml とほぼ 同じ形式ですが、二行目の module: に Module名を記述します。ここでは、back-job という名前をつけます。

余談ですが、app.yaml にも module: を記述できます。しかし記述しないと、default という Module名が記述されたと見なされます。つまりすべてのアプリケーションのインスタンスは、Module下で動いていることになります(何も記述しないと default)。

もう一つ注目して欲しい項目として、instance_class:basic_scaling: があります。それぞれ前回説明した、インスタンス・クラスとスケール・タイプを指定しています。ここではインスタンスクラスは B1 で、スケール・タイプは Basic Scaling を選択しました。これによって制限がないタスクを実行可能です。max_instances: は上限のインスタンス数を指定しますが、必ず記述する必要があります。

idle_timeout: はオプションの設定ですが、Basic Scaling の場合は指定しないと、インスタンスが停止するまでのアイドル時間がデフォルト値の10分になってしまいます。毎時間実行するジョブの場合、一日あたり4時間分も余分なアイドル時間に取られてしまいます。費用削減のためにも、なるべく少ない時間を指定した方が良いでしょうね。

handlers: で、すべてのURLを処理するようにしていますが、login: admin オプションを付けています。Cronで実行するジョブは adminユーザ権限で実行されるため、ジョブの実行には問題ないと同時に不正なアクセスを防止します。

Moduleインスタンスのスタートアップ設定

ちょっとここから???、となる設定です。前回説明した3つのスケール・タイプの内 Manual Scaling と Basic Scaling では、インスタンスのスタートアップのために特殊な設定を行うことが必要です。それはスタートアップ時に、GAEからのGETリスエストが /_ah/start のURLに送信されます。これに応答する必要があります。具体的には 、HTTPステータスコードの200〜299までか404を返すことが必要です。

私は最初次のように、静的HTMLファイルを返せば良いのかなと勘違いしていました。

# この設定は動きません。
# This setting does not work.
handlers:
- url: /_ah/start
  static_files: applications/myapp/static/200.html
  upload: applications/myapp/static/200.html
- url: .*
  script: gaehandler.wsgiapp
  login: admin

この設定では Module は動きません。なぜなら、 /_ah/start リスエスト共にインスタンスを起動してイニシャライズを行うことが必要だからです。静的HTMLファイルを返すだけでは、GAEのインスタンスは起動しません(逆に言えば、静的HTMLだけのアプリなら、GAEではインスタンス費用を払う必要がありません)。

インスタンスを起動するため、web2pyフレームワークの場合なら、_ah.py コントローラを作成し次のように記述します。

_ah.py

# -*- coding: utf-8 -*-
def start(): return "200"

これによって、インスタンスが起動する共にステータスコードの200を返すことができます。

この他に、インスタンス終了時に /_ah/stop というリクエストが送らてきますが、これに関してはアプリケーション側で対応する必要はないようです。

タスクやURLのディスパッチ

最も簡単にタスクを Module に割り当てるには、cron.yaml の target: パラメータに割り当てる Module名を記述します。

cron:
- description: my task
  url: /myapp/job/task
  schedule: every 1 hours
  target: back-job

もし、CronでないタスクやURLを使用する場合は、dispatch.yaml を作成します。

dispatch.yaml

application: myapp

dispatch:
- url: "*/job/*"
  module: back-job

- url: "*/nightjob/*"
  module: back-job

URL毎に Module を指定することができます。

これまた余談ですが、GAEにアップロードした dispatch.yaml の設定を削除する方法がないみたいです。設定を無効にする場合は、dispatch.yaml ファイルを削除するのではなく、設定にコメントを入れてください。これによって設定が無効になります。

Module のアップロード

設定した Module をGAEにアップロードは、GAEランチャーのアップロード機能では対応できないようです。コマンドラインやターミナルやから、次のコマンドを送ってください。

python appcfg.py update back_job.yaml

もしくは

appcfg.py update back_job.yaml

この他、app.yaml 側のアップロードも別途必要です。

もし dispatch.yaml だけを更新したい場合は、次のようなコマンドもあるようです。

appcfg.py update_dispatch ./

Modules API で一番嫌なのは、Module毎にアップロードする必要があることです。面倒な場合、必要なアップロードを全部繋げてバッチファイルを作成しても良いとは思います。

最後に

以上で Modules API の説明を終わりますが、バックエンドの無制限の環境でもジョブが停止することがあります。それはメモリの割当を超えたなどの原因が考えられます。このためジョブを適度な長さに切って、その都度タスクキューに送るなどの工夫が必要になってきます。タスクキューを使い始めると、いろいろプログラムの工夫ができるようになります。タスクキューを使ったことがない方は、Modules API と一緒に使ったら幸せになれると思います。

参考: Python Task Queue Configuration

ところで、暇つぶし用に作ったアプリケーションがあります。最近のメジャーなフレームワークなどをぶっ込んでみました(笑)。

GAE + web2py + Bootstrap + AngularJS + などなど
↓↓↓

↑↑↑
よかったら使ってみてください。