はじめに
前回 までで、WSGIアプリケーションの仕様、アプリケーションの作成、ミドルウェアの利用などの、WSGIの基本的な部分の説明が終わりました。
今回は、作成したWSGIアプリケーションを実行するプラットフォームとして、Google App Engine (GAE) を取り上げます。
Google App Engineとは
Google App Engineとは、Googleが提供しているWebアプリケーションのプラットフォームです。基本的に無料でGoogleのスケーラブルなWebアプリケーションインフラで、自作のWebアプリケーションを動作させることができます。アプリケーションはアカウントごとに10個まで利用できます。アプリケーションごとに利用可能なストレージ容量、 CPU 処理時間、データ転送量などのサーバリソースの制限はありますが、月500万ページビュー規模までは利用できる程度の制限ということなので、個人が利用するには十分だと思います。具体的な制限事項はGAEのFAQ に詳しく記載されているので、必要な方は参照してください。
この記事を執筆している2008年8月現在、GAEでサポートしている言語はPythonのみです。今後Perlをサポートする予定があるようですが、具体的な時期は発表されていません。
アプリケーションの管理には、 Webベースのインターフェースが用意されていて、その画面からアクセスログ、データベースに保存されたデータの確認・変更、クオータの使用量の確認などができます。現在は管理画面からアプリケーションを削除する機能がないため、10個の制限いっぱいまでアプリケーションを作ろうとしている方は、今回のサンプルをアップロードしてみるのは控えた方が良いかもしれません。
図1 アプリケーションの管理画面
GAEで動作させるWebアプリケーションは、GAEサーバ側からCGIとして呼び出されます。そこで、wsgiref.handlers.CGIHandlerを使用して、CGIからWSGIアプリケーションを呼び出すようにすることで、GAEサーバ上でWSGIアプリケーションを動作させることができます。
今回は使用していませんが、GAEにはwebapp という専用のフレームワークが用意されています。webappには、 URLマッピング、 Django というフレームワークで使われているテンプレートエンジンへのラッパ、 Googleのユーザ認証を利用するためのユーティリティなどが存在します。
webappも、Webサーバとの接続にWSGIを使用するため、webappでアプリケーションを作成する際も、既存のミドルウェアを組み合わせて作成することができます。
GAE SDKでの開発
今回は、実際にGAEのサーバでアプリケーションを動作させる前の段階として、ローカルで開発するためのSDKを使用してアプリケーションを動作させてみます。
今回使用するサンプルプログラムは、sample.zip(ZIPで圧縮してあります) にあります。今回のサンプルは、前回同様Hello, world とMessageBoard です。基本的にソースコード自体はほとんど変わりません。変更したのは、メッセージの保存にGAEで提供されるデータベースを使用していることと、実行方法をWSGIサーバからCGIハンドラに変更した程度です。そのため、見た目の動作はまったく同じです。
今回は、実際にGAE上でサンプルを動かしています。以下のURLでアクセスできますので、実際にアクセスして前回までのサンプルと比較してみてください。
Hello, World サンプル
MessageBoardサンプル
SDKのダウンロードとサンプルの実行
実際のサーバで開発を行う前に、ローカルで開発を行うためのSDKを使用してサンプルを動作させることができます。
まず、GAEのダウンロードページ にアクセスして、ご使用のプラットフォームに合ったSDKをダウンロード、インストールしてください。
そして、インストール先のディレクトリに移動し、
図2
$ ./dev_appserver.py ${サンプルのディレクトリ}
とコマンドを入力すると、サンプルが実行できます。
実行後に http://localhost:8080/hello
とhttp://localhost:8080/message
にアクセスすると、前回と同様にページが表示されます。
それでは、前回から追加された部分のースの中身を見ていきましょう。
メッセージボード移植
サンプルプログラムの中身で、前回から追加されたものは、
app.yaml
appmain.py
model.py
です。
app.yaml は、アプリケーションを動作させるために必要な設定ファイルです。
appmain.py は、アプリケーションのエントリポイントで、この中でミドルウェアやアプリケーションの設定を行い、処理しています。
model.py は、書き込みデータをDBに保存するための設定と、入出力のための関数を定義しています。
appmain.pyは、今まで使用していたwsgiref.simple_server.make_serverをwsgiref.handlers.CGIHandlerに変更しただけですので、説明は割愛します。
設定ファイル app.yaml
まずは、アプリケーション設定ファイルapp.yamlを見ていきます。
リスト1 app.yaml
application: wsgisample
version: 1
runtime: python
api_version: 1
handlers:
- url: /.*
script: appmain.py
1行目のアプリケーション名は、実際のサーバ上で動かす際に必要になります。
これは、アプリケーションを作成する際に指定したアプリケーション名で、アプリケーションのドメイン*.appspot.comの* の部分です。今は特に設定する必要もないので、 wsgisample とそのままになっています。
2~4行目は、アプリケーションのバージョンやSDKのバージョンなどの情報が入っています。これらは現状ほぼ定形文なので、そのままにしてください。
handlers 以下の部分は、URLによって呼び出すスクリプトを指定します。
URLの指定には正規表現が使えます。この場合は、すべてのURLに来たリクエストをappmain.pyで処理するように設定しています。
データベースの利用
前回までのMessageBoardでは、アプリケーションをサーバとして動作させていたため、書き込みのデータをすべてメモリ上に保存していました。しかしGAEでは、リクエストが来るたびにプロセスを立ち上げてアプリケーションを実行するため、同じ方法ではリクエストを処理した後にデータが消えてしまいます。そこで、データを保存するために、Googleが提供しているデータベースBigTable を使用します。
データベースの利用というと少しハードルが高そうに思えますが、GAEで提供されているデータベースを使用するのはとても簡単です。データベースを使用するための部分はmodel.py にまとめてあります。
リスト2 model.py
#-*- coding:utf-8 -*-
from google.appengine.ext import db
import datetime
# 書き込みの DB 上のデータを定義する
class Entry(db.Model):
''' DB のモデルを定義 '''
name = db.StringProperty(required=True)
title = db.StringProperty(required=True)
body = db.StringProperty(required=True)
date = db.DateTimeProperty(required=True)
def addEntry(name, title, body):
''' 書き込みを保存する '''
# インスタンスを生成
entry = Entry(name = name,
title = title,
body = body,
date = datetime.datetime.now())
# DB に保存する
entry.put()
def getEntries(num=10, start=0):
''' 書き込みを取得する '''
# 全てのデータに対するクエリを生成
q = Entry.all()
# date が降順になるように並べ替える
q.order('-date')
# start 番目から num 個のエントリを取得
return q.fetch(num, start)
model.pyの中身はEntryクラス、addEntry関数、getEntries関数の3つです。
Entryクラス では、データベースに保存するデータのモデルを定義しています。google.appengine.ext.db.Modelを継承したクラスで、アトリビュートにデータの定義を記述します。データの定義は、dbモジュールにある*Propertyクラスで、StringProperty、DateTimeProperty以外にIntegerPropertyやUserPropertyなどが存在します。
addEntry関数 では、新しいデータベースエントリを追加しています。追加の方法も非常に簡単で、先ほど定義したEntryクラスのインスタンスを作成し、putメソッドを呼ぶだけです。クラスのコンストラクタには、定義した項目をキーワード引数で渡します。
getEntries関数 では、データベースから書き込みデータを取得しています。データベースからデータを読み出す際は、GQLというSQLに似た問い合わせ言語を使用することができます。しかし、今回は複雑な問い合わせを行うわけではないので、クエリオブジェクトを生成して使用しています。
あとはこれらの関数をMessageBoardのaddMessageとlistMessagesで呼び出せば、データの保存と読み込みができます。
まとめ
以上が、前回使用したアプリケーションをGAEで動作させるための変更点です。実際には、データの保存を行う部分とGAE 固有の設定のみですので、それを除くとアプリケーションの動作に影響する部分にはほぼ手を付けていません。GAEは一般的なWeb サーバとは違う特殊な環境ですが、WSGIを利用することにより、ソースコードの変更を最小限に抑えて動作させることができます。
今回は、SDKを使用してWSGIアプリケーションを動作させる、ということに焦点を当てているため、GAEサーバへのアップロードなどは説明していません。 アプリケーションのアップロードなどのより詳しい情報は、GAEのスタートアップガイド を参照してください。
先に述べたように、GAEで利用可能なWebアプリケーションフレームワークには、webapp以外にDjangoというものがあります。DjangoはGAE専用のフレームワークではなく、一般的に利用可能なフレームワークです。Djangoもまた、WSGIから利用することができます。最終回となる次回は、DjangoなどのWSGIで利用できるフレームワークの紹介をする予定です。