App Engine 1.5.0のリリースはかなり大きくて、App Engineはもっと広い範囲でホスティングプラットフォームになりつつありますね。
1.5.0は下記のリンクでダウンロードできる。
http://code.google.com/appengine/downloads.html
バックエンド
バックエンドと言う機能がリリースされました。バックエンドはより制御出来るインスタンス。バックエンドは複数のインスタンスを作ることができます。直接ユーザーからリクエストを処理することもできますし、普通のインスタンスからのリクエストのみを処理するように設定できます。
バックエンドは2つの週類があります。
動的バックエンドはリクエストによって、インスタンス数が増えたり、減ったりするタイプです。ですが、今のところは、20インスタンスまで増える制限があります。
静的インスタンスの場合、インスタンスの数を指定して、そのインスタンスが常に動いているようになります。
実は、Javaはスタートアップが重くて、遅いのですが、立ち上げたら早いので、バックエンドをJavaで書けば、結構早いサーバーを作れるかもしれません。
プル型タスクキュー
APIでアクセスして、処理できるタスクキューをリリースしました。プルキューは普通のタスクキューと同じですが、自動的にタスクを処理するのではなくて、APIでキューに入っているタスクをアクセスして、外部ワーカーで処理する。プルキューでApp Engineで出来ない作業などのタスクを外部サーバーで処理することができる。
APIでタスクを処理する時に、リース(ロック)することが出来ます。リース時間を指定します。リース時間が過ぎたら、リースが解放されて、他のワーカーがタスクをリースすることができるようになります。リース時間の間に処理をしなければならないので、リースのタイムアウトを最悪の時間に近い時間を指定するのが良い。複数のワーカーをリースして、処理する可能性もありますので、App Engineのタスクキューと同じように 冪等 (Idempotent) にしないといけません。つまり、あるタスクが2回以上実行されても大丈夫であるように書かないといけない。
プルキューのドキュメントはこちら:
http://code.google.com/intl/en/appengine/docs/python/taskqueue/overview-pull.html
プルキューを設定する
プルキューをqueue.yaml
で設定します。プル型のキューはmode
プロパティでpull
を指定します。REST APIを使う場合は、ワーカーがタスクキューのデータをアクセスできるために、ACLを指定しないといけません。
queue:
- name: pull-queue
mode: pull
acl:
- user_email: bar@foo.com
- user_email: user@gmail.coum
App Engine でプルキューを使う
タスクをキューに追加する時に、プル型のキューのオブジェクトを生成して、タスクをキューに追加します。タスクオブジェクトを生成する時、payload
とmethod='PULL'
を指定します。payload
はタスクを実行できるためのデータです。バイナリデータ(画像データなど)を使うのも可能。
q = taskqueue.Queue('pull-queue')
tasks = []
payload_str = 'hello world'
tasks.append(taskqueue.Task(payload=payload_str, method='PULL'))
q.add(tasks)
payload
の最大サイズはApp Engineでリースする場合、32MB になりますが、REST APIを使う場合は 1MBしかないので、注意が必要です。1MB 以上のデータを渡さないといけない場合は、Google Storageなどを使って、必要なURLをpayload
に渡すのをおすすめしています。
App Engineでタスクをリースする
App Engine上でタスクをリースするのが簡単。ここに'pull-queue'
というキューのタスクの百件を1時間リースする。
q = taskqueue.Queue('pull-queue')
q.lease_tasks(3600, 100)
App Engineでタスクを削除
処理が終わったら、タスクをタスクキューから削除します。タスクの処理が正常に終わったら、タスクを削除しないとリース時間が切られたら、他のワーカーがリースして処理してしまう。
tasks = queue.lease_tasks(3600, 100)
for task in tasks:
# タスクを処理する
do_work(task)
queue.delete_tasks(tasks)
外部サーバーでグルする
プルキューを使う場合、REST APIでタスクを処理することができるので、カスタムバイナリをつかったり、Perl/Rubyを使ったりするのとか、App Engineで出来ないことが外部サーバーで出来るようになります。
外部サーバーでタスクをリースする
タスクをリースするには、下記のURLにPOST
する
POST
https://www.googleapis.com/taskqueue/v1beta1/projects/{PROJECT_NAME}/taskqueues/{TASKQUEUE_NAME}/tasks/lease?leaseSecs={LEASE_SECONDS}&numTasks={NUM_TASKS}
返ってくるデータはこんな感じです。
{
"kind": "taskqueues#tasks",
"items": [
{
"kind": "taskqueues#task",
"id": string,
"queueName": string,
"payloadBase64": string,
"enqueueTimestamp": number,
"leaseTimestamp": number
},
//...
]
}
ここに、payloadBase64
が返ってくるので、そのデータを使ってタスクを処理する。
外部サーバーでタスクを削除
処理が終わったら、タスクを削除する。
DELETE
https://www.googleapis.com/taskqueue/v1beta1/projects/{PROJECT_NAME}/taskqueues/{TASKQUEUE_NAME}/tasks/{TASK_NAME}
Go ランタイム
Go言語もApp Engineで使えるようになりました。Goはネイティブコードにコンパイルする言語で結構早いですので、App Engineのアプリケーションとして、かなりスケールできるアプリケーションを作れるようになると思います。
App Engineのアプリケーションバージョンで同じapp-id
で複数の言語(Java、Python、Go)を使えるので、重いところだけをGoで書くだとか、フロントエンドインスタンスがPythonで、バックエンドはGoで作られているのとか、いろな仕組みができるのではないかと思います。
Python版の非同期データストア API
今まで、Pythonでデータストアから取得したクエリーの結果がメモリにロードしましたが、クエリーの結果が大きい場合はメモリが不足になったりするのです。
1.5.0でリリースされた非同期APIを使えば、クエリーの結果を一つずつ処理することができますので、メモリに入っているデータが少なくとも済むように処理できます。
非同期APIを使えば、コールバックを指定して、クエリーの結果のエンティティをコールバックに渡して、コールバックの処理が終わったら、メモリから削除することができます(GCで削除)。それで、同時にメモリに載せているデータが少なくて、メモリをそんなに使わなくても済むのです。
新しいプライシングモデル (未確定)
App Engineのプライシングについて、Googleさんはいろいろ考えているらしい。今まで存在したApp Engine for Businessの機能がApp Engine自体に統合し、App
EngineのプランをFree、Paid、Premiumの3つを作りました。Freeのクオータが減ってきますが、Paidのほうの単価が安くなります。ということで、無料で出来ることの範囲が狭くなるが、App Engineの最初の約束、利用した分だけ、お金を払うのがまだまだ続くでしょう。
まとめ
もっと詳しい情報、感想などは、日本で開催されるイベントがいくつかあります。Google I/Oの報告会と、appengine ja night #16で発表する予定です。
僕は参加できませんが、App Engine API
Expert同士@shin1ogawa
さんが発表するGoogle I/O 報告会 in
東京も、大阪で開催されるGoogle I/O 報告会 in
大阪あります。
Google I/Oはいろいろ熱くて、興味を持っている人がたくさんいて、全部人気過ぎてすでに埋まっているのですが。。。