Speicherverlust in der Google App Engine / Datenspeicher / Flask / Python-App

Sep 15 2020

Ich habe eine einfache News-Aggregator-Site erstellt, auf der die Speichernutzung aller meiner App Engine-Instanzen weiter zunimmt, bis das Limit erreicht ist und daher heruntergefahren wird.

Ich habe begonnen, alles aus meiner App zu entfernen, um eine minimal reproduzierbare Version zu erhalten. Das habe ich jetzt:


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
    

Die Statistiken zeigen ein typisches Sägezahnmuster: Beim Start geht es auf 190 - 210 MB, dann erhöht sich bei einigen Anforderungen, aber NICHT ALLEN Anforderungen, die Speichernutzung um 20 - 30 MB. (Dies entspricht übrigens in etwa der geschätzten Größe der Abfrageergebnisse, obwohl ich nicht sicher sein kann, ob dies relevante Informationen sind.) Dies geschieht so lange, bis es 512 MB überschreitet, wenn es heruntergefahren wird. Es passiert normalerweise um die 50. - 100. Anfrage nach "/". In der Zwischenzeit werden keine weiteren Anfragen an andere Personen gestellt.

Wenn ich nun den "for" -Zyklus eliminiere und nur die Abfrage übrig bleibt, verschwindet das Problem, die Speichernutzung bleibt unverändert bei 190 MB, auch nach mehr als 100 Anfragen kein Anstieg.

gc.collect () am Ende hilft nicht. Ich habe auch versucht, den Unterschied in den Tracemalloc-Statistiken zu Beginn und am Ende der Funktion zu untersuchen. Ich habe nichts Nützliches gefunden.

Hat jemand etwas Ähnliches erlebt, bitte? Irgendwelche Ideen, was hier schief gehen könnte? Welche zusätzlichen Tests / Untersuchungen können Sie empfehlen? Handelt es sich möglicherweise um ein Problem mit Google App Engine / Datenspeicher, auf das ich keinen Einfluss habe?

Vielen Dank.

Antworten

1 yedpodtrzitko Sep 17 2020 at 02:48

@Alex in der anderen Antwort hat eine ziemlich gute Recherche durchgeführt, daher werde ich dieser Empfehlung folgen: Versuchen Sie, die NDB-Bibliothek zu verwenden . Alle Aufrufe mit dieser Bibliothek müssen in einen Kontextmanager eingebunden werden, der die Bereinigung nach dem Schließen gewährleisten soll. Das könnte helfen, Ihr Problem zu beheben:

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)
2 Alex Sep 16 2020 at 20:03

Wenn ich nun den "for" -Zyklus eliminiere und nur die Abfrage übrig bleibt, verschwindet das Problem, die Speichernutzung bleibt unverändert bei 190 MB, auch nach mehr als 100 Anfragen kein Anstieg.

query.fetch() Gibt einen Iterator zurück, kein tatsächliches Array der Ergebnisse

https://googleapis.dev/python/datastore/latest/queries.html#google.cloud.datastore.query.Query.fetch

Beim Betrachten des Quellcodes sieht es so aus, als ob dieser Iterator Code zum Abrufen der nächsten Seiten der Abfrage enthält. Ihre for-Schleife erzwingt also, dass alle Seiten der Ergebnisse abgerufen werden. Tatsächlich glaube ich nicht, dass es tatsächlich etwas abruft, bis Sie anfangen zu iterieren. Deshalb würde das Entfernen Ihrer for-Schleife einen Unterschied machen

Leider bin ich mir darüber hinaus nicht sicher, da Sie beim Durchsuchen des Quellcodes ziemlich schnell auf die GRPC-Stubs stoßen und es unklar ist, ob das Problem darin liegt.

Es gibt diese Frage, die Ihrer ähnlich ist, bei der der Fragesteller einen Speicherverlust beim Instanziieren festgestellt hat datastore.Client(). Wie sollte ich einen Speicherverlust untersuchen, wenn ich Python-Bibliotheken von Google Cloud Datastore verwende?

Dies wurde letztendlich mit einem Problem in GRPC in Verbindung gebracht, bei dem GRPC auslaufen würde, wenn es nicht geschlossen würde https://github.com/grpc/grpc/issues/22123

Hoffentlich weist Sie dies in die richtige Richtung