Google App Engine for Java関連の記事が随分と溜まってきましたので、まとめ記事を作ってみました。今後も記事追加時にはこの記事を更新していきたいと思います。
GAE関連ブログをお書きの他の方のように、バックエンドの技術に対する深い考察などはありませんが、実際にアプリケーションを作成してみた上で遭遇したトラブルや小技を書いています。また、なるべくGoogleのドキュメントには記述されていないことを書いたつもりです。
GAEでアプリを開発される方の参考になれば幸いです。
■対象のアプリケーション
次のアプリケーションを作成した上でのTIPSです。
- Cycle Base NANASHI -サイクルベース名無し-
- 自転車用品・パーツのレビューまとめサイト。2ch自転車版からレビューを転載。
- DatastoreへのアクセスにはLow Level APIを使用(2010/1にJDOから変更)。
- 使用しているアプリケーションフレームワークは特になし(2010/1にStruts 1.3の使用を中止)。
■Datastore(JDO)関連
Datastoreの基本
- 使用メモ、Datastore編
- Datastoreの基本的なTIPS。属性の@NotPersistentは重要、開発環境のDatastoreの所在、relationshipのchild側keyの型制限、ServletFilterを使ったPersistenceManagerの管理、entityの取得と属性変更時の挙動など。
- 使用メモ、Datastore GAE編
- Datastoreの基本的なTIPS、GAE環境でのみあてはまるもの。indexの作成時間、relationに順序付けが必要、大量データのアップロード・削除方法など。
- 使用メモ、Datastore cbnanashi@GAE/Jの例
- 当アプリでのクラス構成、datastore-indexes.xmlの例。なお、現在のバージョンではrelationを極力使わないなど単純化している。
- Datastoreの全文検索(LIKE検索)は不可
- 全文検索機能はない。
- Datastore child entityの削除
- List#remove(int)するとエラーになる、他の方法を使う。
Datastore利用アプリ開発時の注意
- Datastoreはバージョン間で共通
- Datastore(Memcacheも)は共通なため、クラス構造(プロパティ等)をバージョン間で変えないように注意が必要。変えたらデータをすべて消すのが無難。
- Datastoreとlazy loading
- entityの属性はlazy loadingではない。親entityのListに対してsize()を呼び出すとListのメンバーがすべてloadされる。
- DatastoreでBlobはlazy loadingされる
- entityの属性のうち、Blob、Textはlazy loadingされる。
その他
- PrimaryKeyをString型にしたとき(?)の不具合
- bidirectionalなrelationshipを持つentityでInvalid Key PBというエラーが出る。SDK 1.2.1で確認。
■Datastore(JDO以外)関連
- Datastoreアクセス時はタイムアウトを考慮するべき
- Datastore利用時は常にタイムアウト発生の可能性があるので考慮してプログラミングする。当アプリでもDatastoreタイムアウト対策を施した結果、正常にリトライされることを確認。
- 集約関数的な処理の実装
- COUNTやSUMなどの処理を実装する方法。プロパティとして保持して変更時に更新する。
- SDK 1.3.1のDatastore自動リトライは地味にすごい(10/02/17)
- SDK 1.3.1の新機能・自動リトライとアプリケーションのリトライ処理方法について。
■Memcache
- Memcacheによるパフォーマンスの改善
- Memcache利用は効果大。当アプリでもcpu_msが半分に。
- Memcache呼出時はtry〜catchで囲むべき
- Memcache呼出時は例外発生を考慮する。
■URL Fetch、Images
- URL Fetch+Imagesでサムネイル作成
- URL FerchとImagesを組み合わせてネット上の画像のサムネイルを作成するコード例。
- 縮小画像の動的生成(10/02/12)
- サムネイル用画像をImagesを用いてリクエスト時に作成する方法。
■GAE上でのJavaプログラミング
- 使用メモ、JSP・Servlet・Struts編
- JSP等の基本的なTIPS。sessionの有効化方法、JSP/Strutsでsessionで使わないための設定、JSPでEL式・JSTLを使うための設定、Action(*.do)をWelcomeページにしたときの注意。
- 使用メモ、その他編
- その他のTIPS。MemcacheにMapを格納したときの注意(Mapの操作は無効)、Google Acountsで取得できるnameについて(@gmail.comが付く)、warディレクトリのupload時の注意等(GAEコマンドを使うとCVSフォルダも公開される、Eclipse plug-inなら無視される)。
- GAE/Jでメンテナンス中画面を出す
- バージョン機能を使って503 Service Unavailableを一時的に返す方法。
- アプリケーションのログの取得
- アプリで出力したログ、およびアクセスログ取得の方法。
- JSP文字化け対策
- SDK 1.2.0で起きていた文字化けへの対策。1.2.1以降は改善されているため現在は不要。
- 静的ファイルに有効期限を設定(09/10/19)
- 静的ファイルのExpiresを設定する方法。appengine-web.xmlのstatic-filesにexpirationを指定する。
- GAE/J、UUを考慮したアクセスカウンタ(09/11/14)
- ユニークユーザーを考慮したアクセスカウンタの作成メモ。MemcacheでIPアドレスを記録する。
■その他、開発環境など
- アプリを独自ドメインで使う
- GAEのアプリを独自ドメインに割り当てる方法のまとめ。
- appspot.comのURLから独自ドメインへの転送
- SEO等のために通常のApp EngineのURLから、301で独自ドメインのURLに転送する方法。
- SDKバージョンアップ時の注意
- SDKバージョンアップ時はEclipseの設定変更が必要、など。
- GAEとDoS攻撃
- DoS攻撃対策について(GAE側には対策機能がないのでアプリ側で対策する)。
- GAEのステータスページ
- ステータスページの所在について。
- GAE/Jアプリ起動時間に関する考察(09/10/14)
- サイズは影響しないようだ(単なる考察でTIPSではありません)。
- GAE/J、SDK 1.2.8のprecompilationの効果(10/01/03)
- 1.2.8で追加されたprecompilationの効果の検証。アプリ起動時間が3割ほど改善された。
- GAE/J、起動時間(spin up時間)短縮の試行錯誤(10/01/26)
- アプリ起動時間短縮の試みについて。クラスローディングを減らすのが有効か。
- GAE/Jで運用中に発生する例外(と一部対処法)(10/02/24)
- 不測の例外とその対策(一部のみ)について。
- GAE/J、5か月間のパフォーマンス推移(10/04/29)
- ウェブマスターツールによる'09/12〜'10/4の5か月間のパフォーマンスの推移グラフ。
- GAE/J用バックアップ/リストアツール作成(10/10/17)
- Datastoreのデータをバックアップ/リストアするApp Engineアプリ+Javaツール。