Apache2 nicht erreichbar während PHP-Sessions gelöscht werden

papagei9

New Member
Hallo,

ab und zu habe ich das Problem, dass durch den Cronjob von PHP

Code:
09,39 *     * * *     root   /usr/bin/nice -n10 [ -x /usr/lib/php5/maxlifetime ] && [ -d /var/lib/php5 ] && find /var/lib/php5/ -type f -cmin +$(/usr/lib/php5/maxlifetime) -delete

der Apache2 ausgebremst wird - wenn ich unter "iotop" folgendes sehe:

Code:
find /var/lib/php5/ -type f -cmin +24 -delete

ist der Webserver nicht erreichbar. Dies dauert eigentlich nur wenige Minuten, ist aber trotzdem sehr ärgerlich ...

Ich weiss nicht, was ich da ändern könnte, damit alles wieder normal funktioniert.

Zum System:

Vor den Apache2 ist als Reverse-Proxy nginx geschaltet.

Ich hoffe, dass wir hier eine Lösung finden können...


Gruss

papagei9
 
Läuft ein Froxlor?

Möglicherweise selbiges Problem wie in diesem Thread ohne ein laufendes Froxlor:

QuickNdirty Workaround: Failtime im nginx auf 30 Sekunden einstellen
 
Hallo, vielen Dank für deine Antwort.

Froxlor verwende ich nicht, aber Confixx.

Das mit dem "failtime" scheint mir ein guter Ansatz zu sein.
Ich finde keinen Eintrag in der /etc/ngnix/nginx.conf

Kannst du mir sagen, wo das "failtime" hin muss?
Hab es auch schon versucht, aber der configtest schlägt fehl...


Gruss

papagei9
 
Last edited by a moderator:
du kannst es mit "ionice -c 3 " versuchen, alternativ ein Skript verwenden welches zwischen 2 Deletes eine kleine Pause (0.01 Sekunde oder so) einlegt und dadurch die anderen Dienste zum Zug lässt.
 
Hey,

mit ionice -c 3 hat es nicht geklappt ... Dieses Problem besteht auch erst, seit ich nginx verwende.

Das mit der Pause zwischen dem Löschen, bringt das was? Weil der "find"-Befehl verursacht die Hauptauslastung .. es werden ja lediglich kleine Session-Dateien gelöscht ...
 
Naja, ich ging davon aus dass dein Skript selbst die Dateien sucht statt find zu benutzen =)

Alternativ, falls du die entsprechenden cgroup-Teile im Kernel hast, kannst du die IOPS des Prozesses beschraenken was aufs gleiche rauskommt.
 
für apache2 brauch ich eigentlich kein rpaf-Modul, nginx übergibt IP, etc alles korrekt.

Naja, ich ging davon aus dass dein Skript selbst die Dateien sucht statt find zu benutzen =)

Was gäbe es denn für Möglichkeiten, die Dateien anderweitig zu suchen? Dann könnt ich mir da sonst was zusammenbasteln...


Ich hab nun zusätzlich bei nginx die Timeouts auf 30 Sekunden heruntergestellt .. Mal schauen was das bringt.
 
Auf der Bash und in anderen Skriptsprachen gibt es sicherlich genug Alternativen, hier eine (ungetestete) PHP-Bastelei, in der Annahme dass deine Dateien alle im gleichen Ordner liegen (nicht rekursiv)
PHP:
#!/usr/bin/php5
<?php
$Location = '/var/lib/php5/';
$DeleteOlderThan = 24;
$SleepFor = 250;    //1000000 microseconds = 1 second

proc_nice(19);
$MaxModified = time() - $DeleteOlderThan * 60; 
$Folder = scandir($Location);
foreach($Folder as $File) {
  if($File == '.' || $File == '..') continue;
  if(!is_file($Location.$File)) continue;
  if(file_ctime($Location.$File) < $MaxModified) unlink($Location.$File);
  usleep($SleepFor);
}
?>

Evtl musst du mit $SleepFor ein wenig herumspielen um einen guten Wert zu finden, 250Mikrosekunden sind je nach Belastung und Wunsch zuviel oder zuwenig.
 
Der einfachste Weg, wäre die Session Files in eine Ramdisk oder tmpfs zu stopfen. Verursacht die geringste IO und das Löschen geht wesentlich schneller.
Weiterhin könnte man den find optimieren, damit er nicht für jede Datei ein rm Prozess forkt, sondern mehrere Dateien auf einmal löscht.
 
Ein kleines, ungetestetes Bashscript, bei dem man die Anzahl der gleichzeitig zu löschenden Dateien und die Wartezeit zwischen den Löschvorgängen einstellen kann. Der Befehl für find geht dabei davon aus, dass alles in einem Unterordner ist. -mindepth und -maxdepth müssen ggf. angepasst werden

Code:
#!/bin/bash

if [ -x /usr/lib/php5/maxlifetime ]; then
	maxlifetime=`/usr/lib/php5/maxlifetime`
fi
filedir='/var/lib/php5/'
sleeptime='0.01'
maxfiles='10'

if [ -d $filedir -a !-z $maxlifetime ]; then
	ionice -n 7 -c 3 nice -n +19 find $yourdir -mindepth 1 -maxdepth 1 -type f -cmin $maxlifetime -print0 | xargs -0 -n $maxfiles | while read files; do
		ionice -n 7 -c 3 nice -n +19 rm $files
		sleep $sleeptime
	done
fi

Nachtrag: den Parameter "-t" scheint es nicht bei allen Paketen zu geben. Z.B. bei Debian 5 ist er nicht verfügbar.
 
Last edited by a moderator:
Hallo,


vielen Dank für die vielen Lösungsansätze bzw. schon fertige Funktionen :)

Alle Dateien befinden sich im gleichen Ordner, es gibt also keine Unterordner.


Die Lösung von d4f sieht sehr interessant aus, da es mit PHP gelöst ist, ich werde jedenfalls alle Vorschläge testen.

Eine Ramdisk für /var/lib/php5 nach Firewire2002 wäre sicherlich auch nicht das schlechteste, wodurch ich vorerst nur die Ramdisk erstellen könnte, um die Performance zu testen.

Auch an Terrorkarotte danke für den Vorschlag.

Ich werde hier dann auch das Resultat mitteilen, nachdem ich diverse Tests durchgeführt habe.


Grüsse

Andi
 
das PHP-Script von d4f führt noch nicht zum gewünschten Ergebnis ...

Bei Terrorkarotte hab ich nun folgendes Problem:

Code:
ionice -n 7 -c 3 nice -n 19 find $filedir -mindepth 1 -maxdepth 1 -type f -cmin $maxlifetime -print0 | xargs -0 -n $maxfiles | while read files; do

gibt folgenden Fehler aus:

Code:
./bash_1.sh: line 10: [: too many arguments

Was kann ich da machen?
 
Da hab ich auch rumgespielt, ja. Ist momentan bei einer Viertelsekunde, habs nun auf 1/2 Sekunde erhöht.
Ich werde dieses Script mindestens noch so lange verwenden, bis ich das andere testen konnte.

Jedenfalls konnte ich die Auswirkung auf den Webserver ein wenig reduzieren, aber es ist immer noch nicht gut.
 
Ich hatte es mit Debian 6 getestet. Dort lief es Problemlos.

Versuch mal folgenden Syntax:
Code:
if [ -d $filedir ] && [ "$maxlifetime" != "" ]; then
 
Modifizier mal $Folder = scandir($Location); dass es so aussieht:
PHP:
$Before = microtime(true);
$Folder = scandir($Location);
echo "Scanned in ".(microtime(true)-$Before)." sec".PHP_EOL;
und copy-paste die Zeit die er ausgibt.

Es koennte gut sien dass der scandir() bei vielen kleinen Dateien viel Last verursacht, in dem Fall muss man es durch ein mehrschrittiges readdir() ersetzen.
Ein tmpfs mit noatime-Mountoption wuerde dein Problem zwar loesen aber eine Angriffsflaeche bieten indem Angreifer viele Sessions erstellen bis du kein RAM mehr hast oder dein tmpfs am Limit ist.
 
Also,

ab und zu dauert das auslesen sehr lange:

Code:
Scanned in 473.781065941 sec

Ich werd das mit readdir noch testen.

PHP GC schau ich mir dann auch noch an, danke.
 
Back
Top