Google App Engine への移行
ここ数日というもの、Mac の前に座ってやっていたことといえば、Twitter か RSS フィードの消化か、でなければブログの移行作業だ。
もともと、このブログは Wordpress で運営していたのだが、色々と不満もたまってきたので、いつの日かつくりなおしたい、と思っていた。おりしも Django の勉強をはじめたばかりである。ちょうどよい。教材代わりに簡単なブログシステムを細々とつくっていた。
それを更に、Google App Engine に移植しましたよ、というのが今回のお話。
Google App Engine に移植した理由
まずは、Google App Engine(以下、GAE)に移植した理由から説明させてほしい。いままで Wordpress を動かしていたサーバでそのまま新しいブログシステムを動かすこともできた。
それでも、わざわざ時間を割いてまで GAE に移植したのは、GAE が話題になってるとか、Django が使えるらしい、というのも重要だったが、自宅サーバの管理から解放されたい 、という理由が実は一番大きい。
うん、自宅サーバの、しかも個人ブログの管理の手間なんて、たかがしれている(そりゃ、セキュリティとかは神経使うけどさ)。それよりは今後、もし、転居や契約している回線業者を変更する場合を考えると、そのあいだは自宅サーバは停めなきゃならないわけで、いまのうちに GAE に移植しておけば、あとあと困らないだろう、というわけである。
実際の移植作業には 4 日程度を要した。
GAE のオンラインドキュメント を参考に、ほとんど単純作業による変換だったが、細かい変更や思わぬ問題などもあったので、開発中にとったメモを片手につらつらと書いてみる。
Django
Django は Running Django on Google App Engine を参考に、開発版のものを動かしている。
GAE では Django の Database API(和訳)は動作せず、GAE の Datastore API を使う必要があるが、当然の帰結として、Database API に依存した機能やアドオンも使えない。Django の売りのひとつである Admin Interface も、サイトマップを手軽に生成できる Sitemap framework も、Generic View でさえ使えない。また、Sites も RequestSite オブジェクトで代替してやらなくてはいけない。
ただ、Generic View は簡単な変更で動きそうだ。実際、Pagination の処理では django.core.QuerySetPaginator
に GAE の Query オブジェクトをそのまま渡して動作していた(GAE の Query オブジェクトも []
アクセスを適切な fetch()
に変換してくれる)。
Akismet
スパムコメント対策として Hashcash と Akismet を使っているのだが、外部リソースへのアクセスは GAE の URL Fetch API に変更が必要だ。Akismet への問い合わせ処理は、外部リソースへのアクセスなので URL Fetch API を使うように変更が必要だった。
docutils, pygments
reStructuredText でブログを書くために docutils を、そして、ソースコードのハイライトするために pygments をソースコードに含めるようにした(トップレベルだと邪魔なので、lib
というディレクトリにパスを通して、そこに必要なライブラリを置くようにした)。
また、docutils はそのままだと、一部 GAE で禁止されているファイルシステム関連の API を使っている。docutils/frontend.py
の
if read_config_files and not self.defaults['_disable_config']:
try:
config_settings = self.get_standard_config_settings()
except ValueError, error:
self.error(error)
self.set_defaults(**config_settings.__dict__)
この部分は潔くコメントアウトした。
検索機能
モデルクラスで db.Model ではなく、そのサブクラスである google.appengine.ext.search.SearchableModel を継承することで、モデルの検索ができるようになるようだ(Indexing Large Chunks of Text for Search - Google App Engine | Google グループ を参照)。「検索機能を備えたクラスを継承する」というだけでもダサいのに、日本語での使用とか不安なので、検索機能はとりあえず見送った。
デプロイして直面した問題
Web アプリケーションの宿命で、最大の問題はデプロイ後にやってくる。
デプロイ直後はすぐに CPU 制限にひっかかってしまう 理由は分からないが、デプロイ直後は GAE の CPU 制限によるエラーが頻発した。これくらいの処理でもういっぱいなのか、と萎えかけたが、しばらくすると正常に動作するようになった。なので、これからもし、同じ現象に遭われた方は、静かな心で見守るのがよいと思う。
データベースの制限でデータ移行ができない 以前のブログからのデータ移行は、dump したデータベースからデータを投入する Python スクリプトを生成する移行スクリプトを用意していた(CSV を使う手段もあるようだが、こっちの方がオブジェクト間の関連を再現するのも楽だ)。
しかし、これが動かない。一度に保存するデータが多すぎると制限にひっかかってエラーになるらしい。
解決策としては、移行処理を機械的に関数に分割して、一度のリクエストでひとつの関数を呼ぶように変更、外部からスクリプトで順番にアクセスさせるようにした。現実の素晴らしき泥臭さ。
favicon.ico と robots.txt の設定
些細なことかもしれないが、favicon.ico と robots.txt の設定をしていなかったせいで、404 エラーが大量に発生してしまった。Google App Engineでfaviconを設定するを参考に app.yaml
を設定した。
- url: /favicon.ico
static_files: public/favicon.ico
upload: public/favicon\.ico
- url: (.*?)/robots.txt
static_files: public/robots.txt
upload: public/robots\.txt
GAE にしてよかったこと・不満
最後に感想でも。
- デプロイも管理も楽
- 思ったよりも速い
- 独自ドメインの設定も簡単だった
- ログの管理や分析とか見過ごしがちな点でもあるので地味に助かる
- 管理インターフェースはまだまだ(特に Django の管理インターフェースを期待していた身としてはつらい)
- ひとつの閉じた世界をいじくってる楽しさがある
最後の点について補足。必要なライブラリはバンドルしなければならないが、それ以外の部分(サーバ管理とか、ミドルウェアとか、ログとか)は無視してアプリケーションの開発に集中できる、という意味で「ひとつの閉じた世界をいじくってる楽しさ」を感じた。そういうこと。
あと 2 つアプリケーション作れるらしいので、何かネタを思いついたら挑戦してみたいですね。