6 Stimmen

Wie kann man Python-Objekte in einer Web-Anwendung persistent machen?

Ich schreibe eine recht komplexe Webanwendung. Das Python-Backend führt einen Algorithmus aus, dessen Zustand von Daten abhängt, die in mehreren miteinander verknüpften Datenbanktabellen gespeichert sind und sich nicht oft ändern, sowie von benutzerspezifischen Daten, die sich oft ändern. Der Zustand des Algorithmus pro Benutzer unterliegt vielen kleinen Änderungen, während ein Benutzer mit der Anwendung arbeitet. Dieser Algorithmus wird während der Arbeit eines jeden Benutzers häufig verwendet, um bestimmte wichtige Entscheidungen zu treffen.

Aus Leistungsgründen ist eine Neuinitialisierung des Zustands bei jeder Anfrage aus den (halbnormalisierten) Datenbankdaten schnell nicht mehr praktikabel. Besser wäre es, das Python-Objekt des Zustands auf irgendeine Weise zwischenzuspeichern, damit es bei Bedarf einfach verwendet und/oder aktualisiert werden kann. Da es sich jedoch um eine Webanwendung handelt, gibt es mehrere Prozesse, die Anfragen bearbeiten, so dass die Verwendung einer globalen Variablen nicht in Frage kommt.

Ich habe versucht, das relevante Objekt (über Pickle) zu serialisieren und die serialisierten Daten in der DB zu speichern, und experimentiere jetzt mit der Zwischenspeicherung der serialisierten Daten über Memcached. Dies hat jedoch immer noch den erheblichen Overhead der Serialisierung und Deserialisierung des Objekts oft.

Ich habe mir Lösungen mit gemeinsamem Speicher angesehen, aber das einzige, was ich gefunden habe, ist POSH . POSH scheint jedoch nicht weit verbreitet zu sein, und es fällt mir nicht leicht, eine solche experimentelle Komponente in meine Anwendung zu integrieren.

Ich brauche einen Rat! Dies ist mein erster Versuch, eine Webanwendung zu entwickeln, also hoffe ich, dass dieses Problem so häufig auftritt, dass es bekannte Lösungen für solche Probleme gibt. An diesem Punkt Lösungen, die davon ausgehen, dass die Python-Back-End auf einem einzigen Server ausgeführt wird, wäre ausreichend, aber Extrapunkte für Lösungen, die auf mehrere Server als auch skalieren :)

Anmerkungen:

  • Ich habe diese Anwendung in Betrieb, derzeit live und mit aktiven Benutzern. Zu Beginn habe ich keine vorzeitige Optimierung vorgenommen und dann nach Bedarf optimiert. Ich habe Messungen und Tests durchgeführt, um sicherzustellen, dass das oben genannte Problem der eigentliche Engpass ist. Ich bin mir ziemlich sicher, dass ich mehr Leistung aus dem aktuellen Setup herausholen könnte, aber ich wollte fragen, ob es einen besseren Weg gibt.
  • Die Einrichtung selbst ist noch nicht abgeschlossen; gehen Sie davon aus, dass die Architektur des Systems so gestaltet werden kann, wie es Ihrer Lösung entspricht.

8voto

S.Lott Punkte 371691

Seien Sie vorsichtig mit einer vorzeitigen Optimierung.

Zusatz: Das "Python-Backend führt einen Algorithmus aus, dessen Zustand..." ist die Sitzung im Web-Framework. Das war's. Lassen Sie das Django-Framework den Session-Status im Cache verwalten. Punkt.

"Der Zustand des Algorithmus pro Benutzer erfährt viele kleine Änderungen, während ein Benutzer mit der Anwendung arbeitet. Die meisten Web-Frameworks bieten ein gecachtes Sitzungsobjekt. Oft ist es sehr leistungsfähig. Siehe Djangos Sitzungsdokumentation für diese.

Ratschläge. [Überarbeitet]

Es scheint, dass Sie etwas haben, das funktioniert. Nutzen Sie die Gelegenheit, Ihr Framework und die Tools kennenzulernen und zu erfahren, an welchen Knöpfen Sie drehen können, ohne ins Schwitzen zu kommen. Insbesondere die Verwendung des Sitzungsstatus.

Zweitens: Tüfteln Sie an Caching, Sitzungsmanagement und anderen Dingen, die sich leicht anpassen lassen, um zu sehen, ob Sie genug Geschwindigkeit haben. Finden Sie heraus, ob MySQL-Socket oder Named Pipe schneller ist, indem Sie beide ausprobieren. Dies sind die Optimierungen, die keine Programmierung erfordern.

Drittens: Messen Sie die Leistung, um Ihren tatsächlichen Engpass zu finden. Seien Sie darauf vorbereitet, die Messungen so feinkörnig zu gestalten (und zu verteidigen), dass sie nützlich und stabil genug sind, um einen sinnvollen Vergleich von Alternativen zu ermöglichen.

Zeigen Sie z. B. den Leistungsunterschied zwischen persistenten Sitzungen und zwischengespeicherten Sitzungen.

4voto

Rafał Dowgird Punkte 40450

Ich denke, dass die Multiprozessorbetrieb Framework verfügt über etwas, das hier anwendbar sein könnte - nämlich das gemeinsame Modul ctypes.

Multiprocessing ist ziemlich neu in Python, so dass es einige Merkwürdigkeiten haben könnte. Ich bin nicht ganz sicher, ob die Lösung mit Prozessen funktioniert, die nicht über multiprocessing .

2voto

JV. Punkte 2530

Ich denke, Sie können ZODB eine Chance geben.

"Ein Hauptmerkmal von ZODB ist die Transparenz. Sie brauchen keinen Code zu schreiben, um Ihre Objekte explizit in eine Datenbank zu lesen oder von ihr zu schreiben. Sie legen Ihre persistenten Objekte einfach in einen Container, der genau wie ein Python-Wörterbuch funktioniert. Alles, was sich in diesem Wörterbuch befindet, wird in der Datenbank gespeichert. Dieses Wörterbuch ist sozusagen die "Wurzel" der Datenbank. Es ist wie eine Wundertüte; jedes Python-Objekt, das Sie darin ablegen, wird persistent."

Ursprünglich war es ein integraler Bestandteil von Zope, aber seit kurzem ist auch ein eigenständiges Paket verfügbar.

Sie hat die folgenden Einschränkungen:

"Es gibt ein paar Einschränkungen, was in der ZODB gespeichert werden kann. Sie können alle Objekte speichern, die in ein standardmäßiges, plattformübergreifendes, serielles Format "eingefügt" werden können. Objekte wie Listen, Wörterbücher und Zahlen können eingefügt werden. Objekte wie Dateien, Sockets und Python-Code-Objekte können nicht in der Datenbank gespeichert werden, da sie nicht "gepickt" werden können.

Ich habe es gelesen, aber noch nicht selbst ausprobiert.

Andere mögliche Sache könnte eine In-Memory-Sqlite-DB sein, die den Prozess ein wenig beschleunigen kann - eine In-Memory-DB zu sein, aber immer noch müssten Sie die Serialisierung Zeug und alle tun. Hinweis: Eine In-Memory-DB ist ressourcenintensiv.

Hier ist ein Link: http://www.zope.org/Documentation/Articles/ZODB1

2voto

M. Utku ALTINKAYA Punkte 2216

Zunächst einmal ist Ihr Ansatz keine gängige Praxis der Webentwicklung. Auch wenn Multi-Threading verwendet wird, sind Webanwendungen so konzipiert, dass sie in Umgebungen mit mehreren Prozessoren laufen können, sowohl aus Gründen der Skalierbarkeit als auch der einfacheren Bereitstellung.

Wenn Sie nur ein großes Objekt initialisieren müssen, das Sie später nicht mehr ändern müssen, können Sie eine globale Variable verwenden, die initialisiert wird, während Ihre WSGI-Anwendung erstellt wird, oder das Modul, das das Objekt enthält, geladen wird usw. Die Mehrfachverarbeitung ist für Sie völlig ausreichend.

Wenn Sie das Objekt ändern und von jedem Thread aus darauf zugreifen müssen, müssen Sie sicher sein, dass Ihr Objekt thread-sicher ist, und Sperren verwenden, um dies zu gewährleisten. Und verwenden Sie einen einzigen Serverkontext, einen Prozess. Jeder Multi-Threading-Python-Server wird Ihnen gute Dienste leisten, auch FCGI ist eine gute Wahl für diese Art von Design.

Wenn jedoch mehrere Threads auf Ihr Objekt zugreifen und es ändern, können die Sperren einen sehr schlechten Effekt auf Ihren Leistungsgewinn haben, was wahrscheinlich alle Vorteile zunichte macht.

2voto

saffsd Punkte 22636

Dies ist Durus, ein persistentes Objektsystem für Anwendungen, die in der Python Programmiersprache geschrieben sind. Durus bietet eine einfache Möglichkeit zur Verwendung und Pflege einer konsistenten Sammlung von Objektinstanzen, die von einem oder mehreren Prozessen verwendet werden. Der Zugriff und die Änderung eines persistenten Instanzen wird über eine zwischengespeicherte Connection-Instanz verwaltet, die commit()- und abort()-Methoden enthält, so dass Änderungen transaktional sind.

http://www.mems-exchange.org/software/durus/

Ich habe es schon einmal in einem Forschungscode verwendet, bei dem ich die Ergebnisse bestimmter Berechnungen aufbewahren wollte. Ich wechselte schließlich zu pytables da es meinen Bedürfnissen besser entsprach.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X