はじめに
昨年の4月7日、GoogleがApp Engine(GAE)というサービスを公開し、申し込みさえすれば誰でもGoogleの巨大なインフラ上でWebサービスを公開することができるようになりました。当初サービス開発に利用できる言語はPythonだけでしたが、今年の5月28日に対応言語としてJavaが追加されました。これは表向きにはJavaのサポートということになっていますが、実際はJVM上で動作する言語であればなんでもよく、GAEのJava版(GAE/J)が公開されて以降、Groovy・PHP・Scalaなど、様々な言語がGAE上で実際に動作しています。
JVMが動く、と聞けばこの連載を読むようなRuby Freaksは真っ先に「JRubyはどうなんだ」と考えたはずです。もちろん、本稿で解説するくらいですから、JRubyも動作します。実のところJRubyはGAE/Jで動くことが最も早く確認された言語の一つで、4月7日にGAE/Jがクローズドベータとして公開された次の日には JRubyのコミッターのOla Bini氏が「JRuby on Rails on Google App Engine 」というエントリを自身のブログで公開しています[1] 。
今回と次回のRuby Freaks Loungeでは、このOra Bini氏の手順を元にGAE/J上で小さなRails製アプリを動かすことを最終目標にしつつ、その周辺について説明したいと思います。
[1] Ora Bini氏のエントリではGoogleアカウントを使ったログイン用のライブラリ、DataStore用のライブラリに加えて、実際に動作する小さなブログシステムのサンプルまで公開されていて「いくら彼が優秀でも流石に早すぎないか?」とびっくりしたんですが、あとでGoogleの方に確認したところ、本当は一般公開される以前からGAE/J上でJRubyを動かすためにGoogleと一緒に作業していたそうです。これはGoogleがGAE/J上でJRubyを使うことを真面目に考えてくれていると解釈して、期待してもいいのではないでしょうか。
GAEについて
GAE/J上でJRubyなどという特異な方向に進む前に、まずはGAEの基本をおさらいしておきましょう。GAEは一言で言えばGoogleが用意した「フルスタック」のWebサービスの開発・運用環境です。Railsもよくフルスタックと呼ばれますが、GAEがそれと大きく異なるのはSDKにWebサーバやDataStore(DBの一種)が含まれるだけではなく、独自のサブドメインを持つ(独自ドメインも設定できます)実運用環境まで付いてくることです。その環境とはつまりGoogleのインフラのことですから、GAE上で動かしているサービスの信頼性やパフォーマンス、スケーラビリティについて開発者はほとんど気にする必要がない、ということになります。
もちろんおいしい話ばかりではなく、いくつか制限もあります。GAEを無料で使った場合のリソースの割り当て(クォータ)はGoogleによって決められていて、一部を抜粋すると、以下のような制限があります(これら以外のクォータについてはこちら を参照してください) 。
表1 無料クォータ抜粋(2009年7月2日、執筆時現在)
項目 制限
HTTPリクエスト数 130万回/日
外向き(GAE→クライアント)転送量 1GB/日
内向き(クライアント→GAE)転送量 1GB/日
CPU時間 6.5CPU時間/日
データストアAPI呼出し回数 1000万呼出/日
データ保存量 1GB
ただし、クォータの一部は有料プランを選択することで増やすことが可能です。つまりサービス開始直後でそれほどリソースが必要とされない場合は無料プランで開始し、アクセスが増えて収入が見込めるようになってきたら有料プランに切り替えて必要なクォータを増やす、という運用が想定されているわけです。有料プランを選択したとしても無料プランのクォータを超えなかった部分に関しては料金が発生しませんから、GAEはWebサービスを始める敷居を大きく下げてくれるのではないでしょうか。
ここまでのようなクォータはGAEの非機能的な制約と見ることができます。それでは次にGAEの特徴を機能的な面から見てみましょう。機能面で最も大きな特徴はGAEではデータベースとして、みなさんの使い慣れたRDBではなく、BigTable というGoogle製のKey/Valueストアを使っているということでしょう。Key/Valueストアについての詳細はこちら を見ていただきたいのですが、簡単に言えばRubyのHashに永続化の機能を持たせたものと考えてください。RDBに比べて仕組みが非常に単純なため、データへのアクセスは高速で分散も容易ですが、RDBでいうORDER BYのような処理には制限がありますし、JOINのような処理については基本的にはアプリケーション側で実装することになります。
その他、アプリケーションはサンドボックス内の動作しか許されていないため、以下のような処理は特徴(制限)があります。
インターネット上の他のコンピュータへのアクセスはSDKが提供するURLフェッチもしくはメールサービスを通じてのみ可能
ファイルへの書き込みは不可。アプリケーションと同時にアップロードしたファイルの読み取りは可能
リクエストに対しレスポンスに30秒以上かかる処理は禁止
GAEとRailsの相性
前節のような特徴を持つGAEですが、実際のところRuby on Railsとの相性はどうなのでしょうか? 個人的な感想としては、以下のような点から「総合的に見て悪くはない」のではないかと考えています。
Railsは開発の段階では非常に生産性の高いフレームワークですが、それを本番環境で稼働させるのは簡単とは言いがたいのが実際です。それは『Railsデプロイ 』というそのものずばりなタイトルの書籍が出版されていることからも分かるでしょう。一方で、GAEアプリケーションのデプロイはこれ以上ないほど簡単です。例えば、Python版では以下のようなコマンドを一つ実行するだけです。
$ appcfg.py update アプリケーション名
Java版に至ってはEclipse上でツールバー上のボタンで開いたダイアログで、Deployボタンを押すだけでデプロイが完了します。
図1 Java版GAEのデプロイ
GAE上での開発にJRuby(on Rails)を使った場合もデプロイ手順は上記と全く変わりませんから、デプロイに関して言えばGAEはRailsの弱点をカバーしていると言ってもいいでしょう。
反対にGAEがRailsの長所を潰してしまう点もあります。その最たるものがRailsのO/RマッパーであるActiveRecordです。 ActiveRecordは内部的にSQLと密に組み合わされている……というか、ある意味ActiveRecordはSQLビルダーですのでRDB抜きには考えられません。そしてGAEはRDBを使っていません。結論としてRuby on RailsをGAE上で動かした場合、ActiveRecordは使えないということになります。この点に関して現時点で決定的な解決策はないのですが、簡易的な代替案としてはOla Bini氏が作成したBumbleというライブラリがあります。詳細については次回ご紹介する予定ですが、参考までにOla Bini氏のブログから簡単な例を一つ挙げてみましょう。
リスト1 Bumbleの使用例(Ola Bini氏のエントリ )
class Blog
include Bumble
ds :name , :owner_id , :created_at
belongs_to :owner , Person
has_many :posts , :Post , :blog_id , :iorder => :created_at
end
あまり複雑なことはできませんが、Bumbleを使うことで、このようにプロパティや関連を宣言的に定義できます。
また将来的にRails3がリリースされてORMとしてMerbのDataMapperが使えるようになったときに期待できる解決策として、dm-datastore-adapter というものもあります。こちらが使えるようになれば、現在MerbのモデルにできることがGAE上でもほぼ全て可能になりますので今後に期待しましょう。
まとめ
GAE上でRailsを動かすことには利点もあれば欠点もあります。しかしRailsの難点であるデプロイに関してはそもそもWebフレームワークの範疇からはみ出していますから、今後とも劇的な改善が見込めるとは思えません。その点をGAEは補う事ができます。対してGAE上でRailsを使う場合の難点であるORMについては、すでにいくつかの代替案が出ていますし、今後も少しずつ改善されていくでしょう。以上のことからRailsを動かす環境としてGAEというのは検討に値すると私は考えています。
今回はあまり具体的な話が出てこない回になってしまいました。次回は実際にGAE上でRailsアプリを動かしてみたいと思っていますのでお楽しみに。