メニュー

2010年8月8日

Google App Engineで、ときどきImportError

Google App Engineで、ときどきImportErrorが出ます。

もちろん開発サーバでは出ませんし、本番でも普通は出ません。ところが、ときどきImportErrorを出しまくるインスタンスがいます。

App Engineでは、一度importされたモジュールはキャッシュされ、2度目以降のimportはキャッシュされたものが使われます。

ところが、初回起動時のimportの途中でDeadlineExceededExceptionが発生した場合に、中途半端なimportが残ってしまい、ImportError多発となるようです。

Issue:
http://code.google.com/p/googleappengine/issues/detail?id=1409

この状態になってしまったインスタンスは、ずっとエラーを投げるので、どうしようもありません。そのインスタンスを終わらせる(スピンダウン)するしかありません。

簡単な方法としては、デプロイがあります。
新たにデプロイをすると、新しいバージョンで起動していくので、ImportErrorから復帰することが出来ます。

もうひとつは @higayasuo さんから聞きましたが、メモリ不足にすると、インスタンスは終了するようです。これはメモリリークのためのリセットの仕組みですね。

試しにメモリを確保しまくってみたところ、以下のログが記録されました。
Exceeded soft memory limit with 278.605 MB after servicing 2 requests total

これによれば、Pythonでは300MBくらいのヒープがあるようです。

"servicing 2 requests" はインスタンスが起動してからのリクエスト処理数ですので、あまり意味はありません。
# メモリリークの調査であれば意味はありますが

また、以下のようにもログが記録されます。

After handling this request, the process that handled this request was found to be using too much memory and
was terminated. This is likely to cause a new process to be used for the next request to your application.
If you see this message frequently, you may have a memory leak in your application.

訳すと

メモリ不足のため、このリクエストの終了後にプロセスは終了します。
これにより、次のリクエストの処理には新しいプロセスが利用されます。
このメッセージが頻繁に出る場合、アプリケーションにメモリリークの可能性があります。

というわけです。

ImportErrorの発生したインスタンスを強制的にスピンダウンするため、
わざとメモリ不足を発生させる……のもありかもしれません。

本当は、import中のDEEで、中途半端なimportをクリア出来ればいいのですが、方法が分かる方がいらっしゃいましたら、教えて頂けるとありがたいです。