2011年09月18日

GAE/PでのBackendsの使い方

Google App Engineには、ユーザーリクエストに応答するためのFrontend Instanceとは別に、裏で黙々と作業するためのBackend Instanceというものがあります。

Frontend Instanceは、リクエストに対する応答という形で処理をし、1回の処理時間もユーザーリクエストに対しては30秒、CronやTask Queueに対しては10分までという制限があります。

しかし、これでは時間のかかる処理をしにくいので、Backendsという機能が追加されました。Backend Instanceには制限時間がなく、いくらでも処理を続けることができます。(サーバの都合で終了する場合もある)

Backendsは、本来はそのような時間のかかる処理のための機能ですが、Backend Instanceの無料枠はFrontend Instanceとは別に9インスタンス時間分あるので、新料金体系で少しでも料金を節約したい場合にも使えます。(FrontendとBackendを合わせれば無料でも33 37インスタンス時間使える)

Backendsの日本語の解説もまだあまりないので、料金節約のためのBackends利用という視点で、簡単に説明しておきます。

クラスと料金

先ほど、9インスタンス時間まで無料で使えると言いましたが、実際にはもう少し複雑です。

Backend Instanceは、それを実行する環境を選択することができ、それによって料金が変わります。この環境の区分をクラスといいます。

クラス メモリ上限 CPU速度 1時間あたりの料金
B1 128MB 600MHz $0.08
B2 256MB 1.2GHz $0.16
B4 512MB 2.4GHz $0.32
B8 1024MB 4.8GHz $0.64

無料枠は$0.72なので、B1クラスなら9時間、B2では4.5時間となります。無料枠内だけで頑張るセコセコ運用では、当然ですがB1クラスを選択します。

ちなみにFrontend Instanceは1時間あたり$0.04なので、無料枠以上に使う場合はFrontendでやりくりした方が節約できそうです。(Python2.7になるまでの間、半額サービス中でした)

動的インスタンスと常駐インスタンス

動的(dynamic)インスタンスは、リクエストによって起動されて、しばらくリクエストがないと自動的に終了されます。新規にインスタンスを立ち上げるときに少し時間がかかる(500ms程度?)ので、そのときの応答が遅くなります。

常駐(resident)インスタンスは、リクエストが来なくても自動的に起動されて居座り続けます。誰もアクセスしてこなくても常にインスタンスが起動しているので、いつでも最速で応答できます。

Frontendでは動的インスタンスが基本で、Always Onという有料オプションを使うと常駐インスタンスにすることができます。

Backendでは常駐インスタンスが基本で、設定によって動的インスタンスを選ぶことができます。

無料枠でBackendの常駐インスタンスを使うと、B1クラスの場合は16時に起動されて25時に終了させられます。それ以外の時間にアクセスしようとすると、503のレスポンスコードが返ってきます。

Backendの設定はbackends.yamlでする

あまり難しい設定もないので、実例を挙げておきます。

backendの名前hoge、B1クラス、動的インスタンスの場合のbackends.yamlは次のようになります。

backends:
- name: hoge
  class: B1
  options: dynamic

Backend Instanceは複数つくることができ、それぞれに固有の名前をつけることができます。

アプリケーション名がpiyoの場合、このBackend Instanceへリクエストを送る場合は、hoge.piyo.appappspot.comでアクセスできます。リクエストのパスから実際に呼び出されるスクリプトは、Frontendと同様にapp.yamlで定義します。

CronからBackend Instanceを呼び出す

cron.yamlでbackendを呼び出すときは、targetを使います。

cron:
- description: oyatsu job
  url: /tasks/oyatsu
  schedule: every day 15:00
  timezone: Asia/Tokyo
  target: hoge

時間によってFrontendとBackendを切り替える場合は次のようにします。

cron:
- description: frontend
  url: /tasks/toilet
  schedule: every 15 minutes from 01:00 to 15:59
  timezone: Asia/Tokyo
- description: backend
  url: /tasks/toilet
  schedule: every 15 minutes from 16:00 to 00:59
  timezone: Asia/Tokyo
  target: hoge

時刻の範囲指定をしたときの終了時刻は実行時間に含まれるので、この場合は終了時刻を16:00ではなく15:59にします。

Task QueueからBackendを呼び出す

Task Queueの場合も、targetで指定します。

from google.appengine.api import taskqueue
taskqueue.add(url='/tasks/onara',countdown=5,target='hoge')

現在はドキュメントのtaskqueue.add()関数の説明になぜかtargetパラメータがありませんが、Taskクラスの方に説明があります。add()関数の引数は、そのままTaskクラスに渡されるので、targetパラメータも使用できます。

target以外にも、urlパラメータにフルパスで指定してもいいようです。1つのbackendで複数のインスタンスが動いている場合に、特定のインスタンスを対象にすることもできるのですが、インスタンスの指定はtargetではできないので、その場合はインスタンスを含んだパスをurlパラメータに指定すればいいようです。

インスタンスがFrontendなのかBackendなのか確認する

時間によってCronの実行をFrontendとBackendで切り替える運用の場合、同じコードがFrontendでもBackendでも実行されます。現在、どちらのインスタンスで実行されているか知りたいときは、backends.get_backend()で名前を取得できます。Frontendで動いている場合は、Noneが返ってきます。

from google.appengine.api import backends
target = backends.get_backend()
if target is None:
  logging.debug('frontend')

Backendで動いている場合は、targetに名前が入ります。そのままTask Queue等のtargetとして使えます。

BackendはGoogle App Engine Launcherからはデプロイできない

これが一番のハマりポイントでしょう。今のところLauncherの[Deploy]ボタンを押しても、何故かBackendは更新されません。Backendの更新には、appcfg.pyを使う必要があります。

アプリケーションのディレクトリでコマンドプロンプトを開いて、次のようにするとBackendを更新できます。

appcfg.py backends . update

FrontendとBackendではサーバが異なり、プログラムコードが共有されないので、ソースコードの修正をしたら両方を更新する必要があります。

appcfg.pyはFrontendの更新や、Cronだけの更新などもできるので、慣れてきたらLauncherよりもappcfg.pyの方が便利です。使い方は、パラメータ無しでappcfg.pyを実行したり、appcfg.py help コマンド と入力すれば教えてくれます。

2011年09月18日 【プログラミング】 | コメント(0) |

この記事へのトラックバック
この記事へのコメント

コメントを書く
お名前: [必須入力]

メールアドレス:

ホームページアドレス:

コメント: [必須入力]

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。