Die Ausführung von Ubuntus Garbage Collection Cron-Job für PHP-Sitzungen dauert 25 Minuten. Warum?

13

Ubuntu hat einen Cron-Job eingerichtet, der alte PHP-Sessions sucht und löscht:

# Look for and purge old sessions every 30 minutes
09,39 *     * * *     root   [ -x /usr/lib/php5/maxlifetime ] \
   && [ -d /var/lib/php5 ] && find /var/lib/php5/ -depth -mindepth 1 \
   -maxdepth 1 -type f -cmin +$(/usr/lib/php5/maxlifetime) ! -execdir \
   fuser -s {} 2> /dev/null \; -delete

Mein Problem ist, dass dieser Prozess sehr lange dauert, mit viel Festplatten-IO. Hier ist mein CPU-Nutzungsdiagramm:

Grafik zur CPU-Auslastung

Die Bereinigung wird durch die blaugrünen Spitzen dargestellt. Zu Beginn des Zeitraums wurden die Bereinigungsaufträge von PHP standardmäßig zu 09 und 39 Minuten geplant. Um 15:00 Uhr habe ich die 39-minütige Zeit von cron entfernt, sodass ein Reinigungsjob, der doppelt so groß ist, halb so häufig ausgeführt wird (Sie können sehen, dass die Spitzen doppelt so breit und halb so häufig werden).

Hier sind die entsprechenden Grafiken für die E / A-Zeit:

IO Zeit

Und Plattenoperationen:

Plattenoperationen

Auf dem Höhepunkt, an dem etwa 14.000 Sitzungen aktiv waren, wird die Bereinigung 25 Minuten lang ausgeführt, wobei anscheinend 100% eines Kerns der CPU und anscheinend 100% der Festplatten-E / A für den gesamten Zeitraum verwendet werden. Warum ist es so ressourcenintensiv? Ein lsTeil des Sitzungsverzeichnisses /var/lib/php5benötigt nur einen Bruchteil einer Sekunde. Warum dauert es dann ganze 25 Minuten, um alte Sitzungen zu kürzen? Kann ich irgendetwas tun, um dies zu beschleunigen?

Das Dateisystem für dieses Gerät ist derzeit ext4 und läuft unter Ubuntu Precise 12.04 64-Bit.

EDIT: Ich vermute, dass die Last auf den ungewöhnlichen Prozess "Fixiereinheit" zurückzuführen ist (da ich erwarte, dass ein einfacher rmein verdammter Anblick schneller ist als die Leistung, die ich sehe). Ich werde die Fixiereinheit entfernen und sehen, was passiert.

thenickdude
quelle
Wie viel Verkehr generiert Ihre Website, um so viele Sitzungen zu generieren?
Michael Hampton

Antworten:

9

Das Entfernen von fusersollte helfen. Dieser Job führt fuserfür jede gefundene Sitzungsdatei einen Befehl aus (prüfen Sie, ob eine Datei geöffnet ist) , was auf einem ausgelasteten System mit 14.000 Sitzungen leicht mehrere Minuten dauern kann. Dies war ein Debian-Fehler (Ubuntu basiert auf Debian).

Anstelle von memcached können Sie auch versuchen, tmpfs (ein Dateisystem im Speicher) für Sitzungsdateien zu verwenden. Wie in memcached würde dies Sitzungen beim Neustart ungültig machen (dies kann umgangen werden, indem dieses Verzeichnis irgendwo im Shutdown-Skript gesichert und im Start-Skript wiederhergestellt wird), ist jedoch viel einfacher einzurichten. Aber es hilft nicht bei fuserProblemen.

Tometzky
quelle
Es hört sich so an, als ob der Fehler in der Fixiereinheit darin bestand, dass eine frühere Version gabelte, aber nach Abschluss nie geerntet wurde, wodurch Tausende von fuserProzessen in einem Zombie-Status Speicher verbrauchten, was zu einem Serverabsturz führte. Ich denke, das wurde bereits in der von mir verwendeten Version von psmisc behoben.
Thenickdude
Das ist ein weiterer Fehler. Sie haben ein einfaches Problem, Tausende von fuserProzessen zu starten , die alle das Ganze /proc/nach offenen Dateien durchsuchen müssen .
Tometzky
9

Herzlichen Glückwunsch zu einer beliebten Website, die die ganze Zeit auf einer virtuellen Maschine ausgeführt werden kann.

Wenn Sie wirklich in zwei Millionen Seitenzugriffen pro Tag ziehen, dann werden Sie eine ganze Reihe von PHP - Sessions im Dateisystem stapeln, und sie werden eine lange Zeit in Anspruch nehmen , egal zu löschen , ob Sie verwenden fuseroder rmoder Staubsauger.

An dieser Stelle empfehle ich Ihnen, nach alternativen Möglichkeiten zum Speichern Ihrer Sitzungen zu suchen:

  • Eine Option ist das Speichern von Sitzungen inmemcached . Dies ist blitzschnell, aber wenn der Server abstürzt oder neu startet, gehen alle Ihre Sitzungen verloren und alle werden abgemeldet.
  • Sie können Sitzungen auch in einer Datenbank speichern. Dies wäre ein bisschen langsamer als im Speicher, aber die Datenbank wäre beständig, und Sie könnten alte Sitzungen mit einer einfachen SQL-Abfrage löschen. Um dies zu implementieren, müssen Sie jedoch einen benutzerdefinierten Sitzungshandler schreiben .
Michael Hampton
quelle
Memcached ist sicherlich eine Option, obwohl es ein separater Pool von unserer Haupt-Memcached-Instanz sein müsste, sonst würden Sitzungen zufällig aus unserem Cache-Druck entfernt. Ich bin jedoch nicht davon überzeugt, dass das Löschen von 14.000 Dateien 25 Minuten dauern sollte. Das hört sich für mich viel zu langsam an. Ich werde ein paar Stunden warten und sehen, wie die Leistung eines Simple rmist.
Thenickdude
Ohne mehr über Ihre Gesamtarchitektur zu wissen, kann ich sie nur empfehlen.
Michael Hampton
Sie können Memcached Server für Redundanz bündeln, indem Sie memcache.session_redundancy = 2 setzen. Siehe serverfault.com/questions/164350/… . Redis ist eine gute Option, wenn Sie sich Gedanken über die Persistenz machen und viel schneller als SQL-Datenbankspeicher sind.
Brunnen
4

Die von den Benutzern hier vorgeschlagenen Speicheroptionen für Memcached-Sitzungen und für Datenbanksitzungen sind daher eine gute Wahl, um die Leistung zu steigern, und haben jeweils ihre eigenen Vor- und Nachteile.

Beim Testen der Leistung stellte ich jedoch fest, dass die enormen Leistungskosten für diese Sitzungswartung fast ausschließlich auf die Anforderungen fuserim Cron-Job zurückzuführen sind. Hier sind die Leistungsdiagramme nach dem Zurücksetzen auf den Natty / Oneiric-Cron-Job, der verwendet rmwird fuser, um alte Sitzungen zu kürzen. Die Umschaltung erfolgt um 2:30 Uhr.

CPU auslastung

Verstrichene IO-Zeit

Plattenoperationen

Sie können sehen, dass der durch die Bereinigung von Ubuntu-PHP-Sitzungen verursachte periodische Leistungsabfall fast vollständig beseitigt ist. Die im Diagramm "Datenträgervorgänge" gezeigten Spitzen sind jetzt viel kleiner und ungefähr so ​​dünn, wie dieses Diagramm möglicherweise messen kann. Dies zeigt eine kleine, kurze Störung, bei der die Serverleistung zuvor 25 Minuten lang erheblich beeinträchtigt wurde. Die zusätzliche CPU-Auslastung entfällt vollständig. Dies ist jetzt ein IO-gebundener Job.

(Ein nicht verwandter E / A-Auftrag wird um 05:00 Uhr und ein CPU-Auftrag um 7:40 Uhr ausgeführt. Beide verursachen ihre eigenen Spitzen in diesen Diagrammen.)

Der geänderte Cron-Job, den ich jetzt ausführe, ist:

09 *     * * *     root   [ -x /usr/lib/php5/maxlifetime ] && \
   [ -d /var/lib/php5 ] && find /var/lib/php5/ -depth -mindepth 1 \
   -maxdepth 1 -type f -cmin +$(/usr/lib/php5/maxlifetime) -print0 \
   | xargs -n 200 -r -0 rm
thenickdude
quelle
-print0 | xargs ...ist nicht nötig - man könnte einfach dort abreisen -delete. Aber es wird in beide Richtungen mit vergleichbarer Geschwindigkeit funktionieren.
Tometzky
1

Ich bin auf diesen Beitrag gestoßen, als ich über Sitzungen recherchiert habe. Die akzeptierte Antwort ist zwar sehr gut (und der Fixier-Aufruf wurde für einige Zeit aus dem gc-Skript entfernt), aber ich denke, es lohnt sich, ein paar andere Überlegungen zu beachten, falls jemand anderes auf ein ähnliches Problem stößt.

In dem beschriebenen Szenario verwendete das OP ext4. Verzeichnisse in ext4 speichern Dateidaten in einem Htree-Datenbankformat - was bedeutet, dass das Speichern vieler Dateien in einem einzigen Verzeichnis nur geringfügige Auswirkungen hat, verglichen mit der Verteilung auf mehrere Verzeichnisse. Dies gilt nicht für alle Dateisysteme. Der Standard-Handler in PHP erlaubt es Ihnen, mehrere Unterverzeichnisse für Sitzungsdateien zu verwenden (beachten Sie jedoch, dass Sie überprüfen sollten, ob der Steuerungsprozess in diese Verzeichnisse rekursiert - der obige Cron-Job nicht).

Ein Großteil der Betriebskosten (nach dem Entfernen des Anrufs an die Fixiereinheit) entsteht durch das Betrachten von Dateien, die noch nicht veraltet sind. Die Verwendung (zum Beispiel) einer einzigen Ebene von Unterverzeichnissen und 16 Cron-Jobs, die in jedem Unterverzeichnis (0 /, 1 /, ... d /, e /, f /) suchen, glätten die auftretenden Belastungsstöße.

Die Verwendung eines benutzerdefinierten Session-Handlers mit einem schnelleren Substrat wird helfen - es gibt jedoch eine große Auswahl (Memcache, Redis, MySQL-Handler-Socket ...), wobei der Qualitätsbereich der im Internet veröffentlichten Sockets, den Sie auswählen, vom genauen Wert abhängt Anforderungen in Bezug auf Ihre Anwendung, Infrastruktur und Kenntnisse, nicht zu vergessen, dass es häufig Unterschiede im Umgang mit Semantik (insbesondere Sperren) im Vergleich zum Standard-Handler gibt.

symcbean
quelle
0

Bei dieser Art von Datenverkehr sollten Sie keine Sitzungen auf ein Dis setzen. Sie sollten so etwas wie Memcache verwenden. Alles was Sie tun müssen, ist PHP einzurichten und es ist keine Codeänderung erforderlich. Siehe zum Beispiel

http://www.dotdeb.org/2008/08/25/storing-your-php-sessions-using-memcached/

Der Grund, warum es so lange dauert, ist die riesige Menge an Dateien, die sortiert werden müssen, um zu sehen, welche gelöscht werden können. Memcache kann diese aufgrund der in Ihrem Code festgelegten Sitzungsdauer automatisch ablaufen lassen.

Mike
quelle