Große PHP-Sitzung verlangsamt Web-Anwendung

8

Ich habe eine Webanwendung, in der komplexe Berechtigungen bestimmen, ob ein Benutzer Zugriff auf Tausende von verschiedenen Dateien hat. Ein Benutzer kann alle Dateien sehen, aber es gibt einen Indikator, um Dateien zu öffnen, auf die er Zugriff hat. Ein Benutzer hat Zugriff auf eine Datei, wenn ein anderer Benutzer in seiner Organisation darauf zugreifen kann oder wenn ein Benutzer, mit dem eine Zusammenarbeit besteht, Zugriff auf diese Datei hat.

Im Moment habe ich eine komplexe PHP-Funktion, die eine große PHP-Sitzung erzeugt, indem sie Arrays der Dateien erstellt, auf die ein Benutzer entweder in ihrer Organisation oder ihren Kollaborationen zugreifen kann, und diese Access-Arrays zusammenführt. Wenn diese Dateien dem Benutzer angezeigt werden, prüft PHP dieses Array, um zu sehen, ob sie Zugriff haben, und wenn dies der Fall ist, fügt es die Schaltfläche hinzu, um die Datei zu öffnen. Ich mache es auf diese Weise, weil das Ausführen der Abfrage, um den Zugriff für jede einzelne Datei zu überprüfen, beim Anzeigen langer Dateilisten viel zu lange dauerte und PHP in_array () wesentlich schneller war.

Das Problem ist ...

Die PHP-Sitzung ist so groß geworden, dass sie scheinbar einfache Website-Funktionen zu einem Crawl verlangsamt, und ich muss mir einen neuen Weg vorstellen, dies zu tun.

Meine Frage ist ...

Was wäre der beste Weg, um PHP-Sitzungen zum Speichern von Dateiberechtigungen und Dateispeicherorten für Tausende von Dateien zu ersetzen, auf die ein Benutzer zugreifen kann, damit PHP bei der Anzeige von Dateilisten diese Informationen schnell abrufen kann, ohne dass dies erforderlich ist eine Abfrage für jede einzelne Datei ausführen?

    
skiindude22 24.09.2011, 20:32
quelle

2 Antworten

6

Hm, ohne den vollen Umfang des Problems zu kennen, würde ich vorschlagen, eine Tabelle Sessions in Ihre Datenbank einzufügen und ein Feld FilePermissions und ein Feld UserId einzufügen.

Dieses Feld würde eine JSON-Darstellung Ihrer Berechtigungsstruktur speichern. Dies würde nur einen Aufruf an die Datenbank erfordern, und der Großteil der Verarbeitung würde stattfinden, während die json-Daten-Server-Seite analysiert wird (was überhaupt nicht viel Overhead sein sollte).

Dies ist eine Standardmethode, um die Größe von clientseitigen Sitzungsinformationen zu reduzieren. Eine gute Faustregel ist, alles in die Tabelle Sessions zu setzen, die die Logik Ihrer Anwendung offen legt.

Aktualisieren

Ich würde nur die Dateien speichern, auf die im json-Feld Zugriff haben. Es kann davon ausgegangen werden, dass eine Nicht-Existenz es ihnen verbietet, auf die Dateien zuzugreifen. Dies würde wiederum den Leistungsbedarf reduzieren.

Dies würde nur funktionieren, wenn es keine komplexe Berechtigungsstruktur gibt (wie jede Datei über Lese- und Schreibrechte verfügt). Wenn nicht, würde ich sagen, Sie sind im klaren.

    
Chuck Callebs 24.09.2011 20:44
quelle
0

Ich bin mir nicht sicher, dass es viel gibt, was Sie tun können. Vielleicht kann memcached helfen, aber ich habe es nicht benutzt (obwohl, von dem, was ich gehört habe, das ist, wofür es verwendet wird).

Sie könnten das Array in einer Datei persistieren, obwohl das, soweit ich weiß, genau das ist, was Sitzungen tun.

Sie können auch shared memory verwenden, um die Benutzerdaten zwischen den Skriptstarts im Arbeitsspeicher zu erhalten.

Benötigen Sie wirklich die gesamte Liste der Benutzerberechtigungen in einem einzigen Array? Das heißt, zeigen Sie dem Benutzer immer Tausende von Dateien an? Wenn ja warum? Wäre es möglich, das System mit AJAX neu zu entwerfen, um nur einen Teil der Dateien zu laden?

UPDATE: Eine andere Idee.

Sie können auch die Berechtigungen des Benutzers für jede Datei vorberechnen und diese in der Datenbank speichern. Die Tabelle könnte FilesPermittedPerUser heißen und den zweispaltigen Primärschlüssel userID / fileID haben. Dadurch wird ein Index erstellt, der zuerst nach userID und dann nach fileID sortiert wird. Ein zweispaltiger Schlüssel würde auch die Eindeutigkeit der Einträge erzwingen.

Da es dann vom Benutzer indiziert wird, können Sie einfach ORDER BY userID und LIMIT 10, 10 nur die Dateien 10-20 auflisten. Wenn Sie nur Teile der Liste über AJAX abrufen, würden Sie nie die schreckliche Speicherlast verursachen, die Ihre Skripte derzeit verursachen.

Es würde nur erfordern, dass die Berechtigungen der Datei aktualisiert werden (zB Datei wird erstellt, Datei wird gelöscht, Gruppenberechtigungen werden geändert, Gruppenmitgliedschaft des Benutzers wird geändert, Gruppenzugehörigkeit der Datei wird geändert ...) müsste die Tabelle aktualisieren. Ich vermute, das sollte nicht zu schwierig sein. Stellen Sie nur sicher, dass Sie das Update in einer Transaktion zwischenspeichern, um die Atomizität des Vorgangs zu erhalten.

Sie können das Dateisystem auch in Ordnern organisieren. Es macht sehr wenig Sinn, nur Tonnen von Dateien an Benutzer zu werfen und sie ständig zu pflegen. Versuchen Sie 10.000 Dateien im Explorer / Finder / Nautilus zu werfen und sehen Sie, was passiert, wenn Sie diesen Ordner öffnen. Nichts nettes, und sie können die Erinnerung behalten - und mit PHP nicht.

Abschließende Idee (obwohl Sie wahrscheinlich nicht zu diesen Extremen gehen müssen): schreiben Sie Dateisystem APIs in etwas, das nicht PHP ist und die Erlaubnisdaten herum behalten können. Verwenden Sie PHP nur zum Weiterleiten von Anfragen an diesen benutzerdefinierten Server, der auf einem anderen Server ausgeführt wird.

    
Ivan Vučica 24.09.2011 20:45
quelle

Tags und Links