Google App Engine / Datastore / Flask / Pythonアプリのメモリリーク
シンプルなニュースアグリゲーターサイトを構築しました。このサイトでは、すべてのApp Engineインスタンスのメモリ使用量が制限に達するまで増加し続け、シャットダウンされます。
最小限の再現可能なバージョンに到達するために、アプリからすべてを排除し始めました。これは私が今持っているものです:
app = Flask(__name__)
datastore_client = datastore.Client()
@app.route('/')
def root():
query = datastore_client.query(kind='source')
query.order = ['list_sequence']
sources = query.fetch()
for source in sources:
pass
統計は、典型的なのこぎり波のパターンを示しています。インスタンスの起動時に190〜210 Mbになり、すべてのリクエストではなく一部のリクエストで、メモリ使用量が20〜30Mb増加します。(ちなみに、これはクエリ結果の推定サイズにほぼ対応しますが、これが関連情報であるかどうかはわかりません。)これは、シャットダウン時に512Mbを超えるまで発生し続けます。これは通常、「/」への50〜100番目のリクエストで発生します。その間、他のリクエストは行われません。
ここで、「for」サイクルを削除し、クエリのみが残っている場合、問題は解消され、メモリ使用量は190 Mbフラットのままであり、100回以上のリクエストの後でも増加しません。
最後のgc.collect()は役に立ちません。また、関数の最初と最後のtracemalloc統計の違いを調べてみましたが、何も役に立ちませんでした。
誰かが似たようなことを経験したことがありますか?ここで何がうまくいかない可能性があるアイデアはありますか?どのような追加のテスト/調査をお勧めできますか?これは、私が制御できないGoogle App Engine /データストアの問題である可能性がありますか?
ありがとうございました。
回答
他の回答の@Alexはかなり良い調査を行ったので、この推奨事項をフォローアップします。NDBライブラリを使用してみてください。このライブラリを使用するすべての呼び出しは、コンテキストマネージャにラップする必要があります。これにより、閉じた後のクリーンアップが保証されます。それはあなたの問題を解決するのに役立つかもしれません:
ndb_client = ndb.Client(**init_client)
with ndb_client.context():
query = MyModel.query().order(MyModel.my_column)
sources = query.fetch()
for source in sources:
pass
# if you try to query DataStore outside the context manager, it will raise an error
query = MyModel.query().order(MyModel.my_column)
ここで、「for」サイクルを削除し、クエリのみが残っている場合、問題は解消され、メモリ使用量は190 Mbフラットのままであり、100回以上のリクエストの後でも増加しません。
query.fetch() 結果の実際の配列ではなく、イテレータを返します
https://googleapis.dev/python/datastore/latest/queries.html#google.cloud.datastore.query.Query.fetch
ソースコードを見ると、このイテレータにはクエリの次のページをフェッチするためのコードがあるようです。つまり、forループは、結果のすべてのページをフェッチするように強制します。実際、反復を開始するまで、実際には何もフェッチしないと思います。そのため、forループを削除すると違いが生じます
残念ながら、それ以上のことはわかりません。ソースコードを掘り下げると、すぐにGRPCスタブに遭遇し、問題がそこにあるかどうかが不明だからです。
質問者がインスタンス化に関連するメモリリークを発見した、あなたの質問に似たこの質問がありますdatastore.Client()。Google Cloud Datastore Pythonライブラリを使用するときにメモリリークを調査するにはどうすればよいですか?
これは最終的に、GRPCが閉じられないと、GRPCがリークするというGRPCの問題にリンクされました。 https://github.com/grpc/grpc/issues/22123
うまくいけば、これはあなたを正しい方向に向けます