2011年11月1日火曜日

【備忘録】 GAEでPython2.5からPython2.7へマイグレーションするには

まだ途中なんだけど、GAEがPython2.7に対応した(但、experimental)。

Python2.7になると何が嬉しいかって、新料金体系で制限が厳しくなったインスタンス起動時間の制限を、スレッドの利用によって回避できる(かも?)なこと。

ちゅうことで、今はPython2.5で作られているPush It!サーバをPython2.7化しようと目論見中なのだが、若干はまったので、備忘録としておく。

とりあえずこの辺とかこの辺とかは読んどくこと。必要なことは多分ここから全部たどれる。

①アプリケーションの新規作成

Python25で作ってあるアプリケーションをPython27に変更できるかどうかは調べていないので不明だが、少なくとも現状DatastoreをMaster/Slaveにしている場合は、Python27だとHigh Replication一択なので、新規に作成しておく必要がある。

②app.yamlの変更(その1)

とりあえず、以下は必須だ。
-runtime: python
+runtime: python27

①でアプリケーションを新規作成した場合はapplicationも変更しておこう。

それから、後でも良いが、スレッドを使いたい場合は、
+threadsafe: true
も付けておこう。
ただし、threadsafeでないライブラリを使ってない場合は実行時に怒られるぞ。 アプリがthreadsafeかどうかは実装次第なのでそこは自前で頑張ること。

Djangoを使っている場合は、
+libraries:
+- name: django
+  version: "1.2"
こんなのもいるのだが、しかし、google.appengine.ext.webapp.templateとしてDjangoのTemplate機能のみを使っている場合は不要っぽい。

③webapp2を使用するように変更する
webappフレームワークがwebapp2となりましたのでimportするモジュールを変更する。
が、しかし、Python27 on GAE環境ではwebappという選択肢がないので、webappモジュールはwebapp2へのエイリアスとなっている。
従って、結論としては変更の必要なし。

④とりあえずサーバにアップしてみよう

尚、Python27版のSDKは「ない」。ローカルでテストできないので必然的にサーバにアップしてテストすることになる。
アップロードの仕方は以前と変わりなし。

で、エラーになった。

app.yamlで怒られる。CGI Handlerはthreadsafeではありません、とな?
ここをよくよく見てみよう。

script: main.app

と書いてあるでしょう。
紆余曲折ありつつも、これは、main.pyのappという変数にマッピングすることを意味しているらしいことが分かる。なので、以下に続く。

⑤app.yamlの変更(その2)

④に書いた通り、

-script: main.py
+script: main.app
てな感じに修正する(mainはあくまで例。任意のハンドラスクリプト名に置き換える)。
appが予約語なのか、main.pyのWSGIApplicationのインスタンスを指す変数名ならなんでも良いのか、は不明。

⑥ハンドラスクリプトの修正

③に書いた通り、webappほげほげのimportはエイリアスが張られているので変更不要。
変更が必要なところは、ここに書いてある。
要するにmain関数が不要になり、WSGIApplicationのインスタンスをappという名前の変数に格納する、ということ。

⑦サーバにアップロードする(2回目)

さあ、これで準備は整いました。
アップロードして、アクセスしてみよう。
よほど特殊なことをしていない限りは多分、それなりに動くはず。

⑧Django1.2対応

⑦でそれなりに動くことは動くんだが、Djangoのバージョンが0.96から1.2に変わっている影響で、templateモジュールに若干の変更あり。

テンプレートに埋め込む変数値が、0.96ではデフォルトではエスケープされないところ、1.2ではデフォルトでエスケープされるようになった。
なんらかの理由によりスクリプト側から既にエスケープした状態の値をテンプレートに渡している場合、二重にエスケープされることになるので、

somevariable|safe

みたいな感じで書いてあげること。
あと、HTMLタグを含む値(などのHTML的に意味のある値)を、HTMLタグとして埋め込みたい場合とかね。

⑨High Replication Datastoreへの対応

普通のアプリケーションなら⑧までやれば、それなりに動くようにはなるので、Python27化はそれほど高い敷居ではありません。

さて、問題はこれです。
従来、GAEのDatastoreはMaster/Slave(MSD)という構成でした。
MSDは1年ちょっと前にトラブルが続発していたことがあり、その反省から生まれたのが、High Replication Datastore(HRD)です。
以降、GAEでアプリケーションを新規作成する際には、MSDかHRDのどちらかを選ぶことができるようになりました。ですが、そのアプリケーションでは新規作成時以外ではDatastoreを変更することはできません。

どちらを選ぶべきか、は、この辺に書かれているのですが、気になるのは、
  • Python2.7ではHRDしか選択肢がない(GoogleさんはMSDを捨てたい、と思っているのでしょう)
  • Consistency(日本語にすると一貫性とか整合性、かな?)の「Most Queries」がStrongからEventualになっている。
Eventual...つまりどういうことか?というのが分かりやすく書かれているのがこの辺になります。

意訳すると、データの一貫性は保たれるが、インデックスの一貫性は保証できねー、ということらしい。インデックスを使わない(つまりクエリーを使わない)で、キーなどを使ってデータに辿りつける場合は無問題。クエリー使うと、最新でない結果セットが取れちゃうかもよ、てなことだそうだ。

情報系(ブログとかニュースとか)などのサイトであれば、多少結果が古かろうと「まあいいよね?」で済むと思うんだが、Push It!はしかし、そうではない。一貫性が保証されないと、クライアントとの同期が維持できない。
困ったことだよ・・・。

回避策としてはmemcacheの利用などが挙げられているものの、memcacheって揮発性だから、なくなっちゃった状態から、どうやって「最新と保証できる」memcacheを構築できるのか、全く思いつかない。
全ての情報がキーから辿れるなら(そしてそのキーが可知であれば)問題ないですけど、そんな風には作ってないわけで・・・。

しかし、今回のブログはリンクいっぱい埋め込んだな・・・。情報分散しすぎなんだよ・・・。

0 件のコメント: