WSGIとPythonでスマートなWebアプリケーション開発を

第4回Google App EngineでWSGIを使う

はじめに

前回までで、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 アプリケーションの管理画面
図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, worldMessageBoardです。基本的にソースコード自体はほとんど変わりません。変更したのは、メッセージの保存にGAEで提供されるデータベースを使用していることと、実行方法をWSGIサーバからCGIハンドラに変更した程度です。そのため、見た目の動作はまったく同じです。

今回は、実際にGAE上でサンプルを動かしています。以下のURLでアクセスできますので、実際にアクセスして前回までのサンプルと比較してみてください。

Hello, World サンプル
MessageBoardサンプル

SDKのダウンロードとサンプルの実行

実際のサーバで開発を行う前に、ローカルで開発を行うためのSDKを使用してサンプルを動作させることができます。

まず、GAEのダウンロードページにアクセスして、ご使用のプラットフォームに合ったSDKをダウンロード、インストールしてください。

そして、インストール先のディレクトリに移動し、

図2
$ ./dev_appserver.py ${サンプルのディレクトリ}

とコマンドを入力すると、サンプルが実行できます。

実行後に http://localhost:8080/hellohttp://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で利用できるフレームワークの紹介をする予定です。

おすすめ記事

記事・ニュース一覧