Google APP Engine の新機能Backendsの解説

 Google IO 2011あわせのアップデートで、Google APP EngineにBackendが導入されました(Python/Java)。
 これはbackendと呼ばれるずっと立ち上がりっぱなしのインスタンスを提供する仕組みで、時間制限がありません。そのため、大規模、あるいは長時間かかるような処理に向いています。

Backendsの設定から処理の受付まで

 Backendsの設定から起動までは次のようになります

  1. 設定ファイル(backends.yaml/xml)で各backendを設定
  2. アプリをデプロイ(backend内の処理はアプリ内の処理の一部という形)
  3. appcfgから起動
  4. 各backendに割り振られたURLにリクエストする

 appcfgにはこのほかに停止や削除と言った管理用のコマンドがあります(Python/Java)

Backendsの設定

 前述したとおり、backends.yaml/xmlで各backendを設定します。
 backendには、次のような設定項目があります

name

 唯一の必須項目。backendの名前です。backendにはそれぞれURLが割り振られていてリクエストすることができますが、その決定に必要となります。

class

 backendのインスタンスに割り振られるCPUとメモリを決定します。B1,B2,B4,B8の三種類があり(Python/Java)、デフォルトではB2(256MB・1.2GHz)です。

instances

 このbackendとしていくつのインスタンスを立ち上げるかを決定します。1〜20まで設定可能です。
 python版では各インスタンスは一度にひとつのリクエストのみ処理できます。java版ではthreadsafeがマークされていた場合のみ複数リクエストを処理できます。

max-concurrent-requests

 java版のみ。複数リクエストを受け付ける場合の最大数を設定します。未設定の場合、状況に応じて処理するとのことです

start(Python版のみ)

 実験段階です。インスタンスの開始時に動作するスクリプトをapp.yamlの設定を無視して設定します。

options

 オプション設定です。複数指定可能とあるのですが、yamlの場合はどう書けばいいのか今のところわかりません。

dynamic

 通常は起動したら即座に設定された数のインスタンスが立ち上がるResidentと呼ばれるインスタンスですが、このオプションを設定するとリクエストを受け付けるようになるだけで、起動そのものはリクエスト数に応じて行われます。
 また、マニュアルまたはGoogle App Engine側の要請に応じたばあいのみシャットダウンされるResidentと違い、処理終了後には数分で自動的にシャットダウンします

public

 これも実験段階です。
 web上から自由にインスタンスにアクセスすることができるようにします。
 予想外に重い処理などが来る場合に注意、とのこと。

failfast

 実験段階です。一つのインスタンスに対して同時処理リクエスト数の上限(python版では一つ)に達した時、処理可能になるまで待機するのではなく即座にエラーを返して失敗させます。

起動時と終了時の処理を設定する

 各backendのインスタンスには起動時には/_ah/startにgetリクエストが送られますので、これを受け取るコードを記述することで初期処理を書くことかできます。
 
 終了時の処理は特殊で、ログには/_ah/stopに対するリクエストとして記録されますが、実際にはリクエストとしては処理されず、終了時のフックとして処理を設定する必要があります(Python/Java)。おそらく起動時処理の際に設定するのがベストでしょう。

backendのURLとTaskQueueでの利用

 各backendにはURLが設定されています。URLは前述したように設定ファイルで設定した名前を元に決定されます。
 
 インスタンスを個別に指定しない場合、

[backendの名前].[アプリケーションのID].appspot.com

 インスタンスを個別に指定する場合は

[インスタンスのID].[backendの名前].[アプリケーションのID].appspot.com

 がそれぞれURLとなります。
 TaskQueueでインスタンスを利用したい場合、Pythonでは引数targetにbackendについてのパラメーターを指定します

from google.appengine.api import taskqueue

    def post(self):
        key = self.request.get('key')

        # デフォルトのキューに追加
        taskqueue.add(url='/path/to/my/worker/', params={'key': key},
        target='1.backend1')#backend1のid「1」インスタンスにリクエストする
   
        #taskqueue.add(url='/path/to/my/worker/', params={'key': key},
        target='backend1')#backend1のいずれかのインスタンスにリクエストする

 
 javaの場合はリクエストヘッダのHOSTにURLを指定します

import com.google.appengine.api.taskqueue.Queue;
import com.google.appengine.api.taskqueue.QueueFactory;
import static com.google.appengine.api.taskqueue.TaskOptions.Builder.*;
import com.google.appengine.api.backends.*;


    queue.add(withUrl("/path/to/my/worker").param("key", key).header("Host",   BackendServiceFactory.getBackendService().getBackendAddress("backend1", 1));#backend1のid「1」インスタンスにリクエストする

課金と制限

 Backendsにはアプリケーション単位での制限があります
 また、起動中は一時間当たりインスタンスクラスに応じた課金が発生します。