Schick programmiert

Sessions in PHP und ihre Tücken

Seit einiger Zeit kämpfe ich mit der Herausforderung rund um simultane Anfragen an eine PHP-Seite. Dass diese Seite mit Symfony2 läuft, hat in diesem Falle nichts zu sagen.

Diese Website hat verschiedene Bilder eingebunden, die zur Laufzeit generiert werden. Über eine .htaccess-Datei wird eine PHP-Datei angesprochen, falls eine Datei nicht existiert. War dies eine Anfrage nach einem Bild, versucht das Script die entsprechende verkleinerte Version zu generieren.

Auf dieser Seite ist auch eine Suche implementiert. Je Seite bekommt der Benutzer dort maximal 50 Ergebnisse angezeigt. Heißt – bei einem Seitenaufruf muss es möglich sein, 50 Bilder generieren zu können.

Bei meinen Tests startete jede dieser 50 Anfragen ein PHP-Script, welches zuerst geprüfte, ob der Benutzer angemeldet ist, dann das Bild generierte und ausgab.

Der Flaschenhals bei dieser ganzen Aktion machte sich deutlich, als ich begann einen PHP Profiler (xhprof in meinem Fall) zu nutzen und ein solches Szenario auf Geschwindigkeit zu testen.

Die Funktion session_start() benötigte bei fast jeder Anfrage um die 10 Sekunden – genau so lange, wie es dauerte die Bilder zu generieren.

Nach einigem Einlesen in PHP und Sessions, fand ich heraus, dass ich den standard SessionHandler von PHP nutze, der die Session in Dateien speichert. Sobald eine dieser Dateien geöffnet wurde, wird sie gelockt, sodass kein zweiter Prozess diese Datei ändern kann. Dies geschieht alles im PHP Core.

Symfony2 hat hier eine gute – aber nicht ungefährliche – Lösung gefunden, die in 95% der Fälle auch gut genug ist. Sie erstellen einen eigenen SessionHandler, der die Werte aus dem Speicher (Datei, Memcache(d), Redis usw.) ausliest, diese aber nicht für weitere Prozesse sperrt. Die Funktion, in der PHP die Sperre legt, ist hier beschrieben: http://de1.php.net/manual/en/sessionhandlerinterface.read.php

Hier noch ein Link zu den genannten Implementierungen des SessionHandlers für Symfony2 – zum Abgucken für dein eigenes System 😉 https://github.com/symfony/symfony/tree/master/src/Symfony/Component/HttpFoundation/Session/Storage/Handler

Das Problem, welches sich hierbei aber ergibt ist, wenn man mehrere Prozesse auf die gleiche Session zugreifen lassen möchte, und beide diese Session bearbeiten, werden (theoretisch) die Änderungen des letzten alle Änderungen der vorigen Prozesse überschreiben.

Dazu auch ein Link: http://www.matt-knight.co.uk/2011/concurrent-php-sessions/
Auf dieser Seite findet ihr auch viel Dokumentation zu diesem Thema.

Meine Anwendung fiel hier auch unter die 95%. Wenn jemand noch mehr Hintergrundwissen braucht, so habe ich einiges mehr an Informationen zu diesem Thema in diesem Post verfasst: http://forum.nginx.org/read.php?3,198958,240954#msg-240954
Andernfalls hilft auch eine Suche mit den Stichworten „php session blocking“.


Categorised as: Uncategorized


Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.