Die zweite Version des Apache-Webservers hat einige interessante Neuigkeiten mit sich gebracht. Unter anderem das mpm-worker-Modul, welches nun Multi-Threading unterstützt; im Gegensatz zur ersten Version des Indianders wird hier nicht mehr für jede Anfrage eigener Prozess gestartet(mpm-prefork), sondern dynamisch Threads in einer kleinen Anzahl von Prozessen erzeugt. Dieser Vorgang hat nicht nur einen geringeren Speicherverbrauch als das alte Modul, sondern kann unter optimalen Voraussetzungen auch eine weit aus höhere Performance erzielen, dazu später mehr.
Neben viel Licht gibt es auch Schatten, die einfache und sehr perfomante Verwendung des Apache PHP Moduls mod_php ist nicht mehr möglich, da das worker-Modul nicht threadsafe ist – Prozesse haben im Gegensatz zu Threads einen eigenen Speicherbereich "und können sich nicht gegenseitig ins Gehege kommen".
Aber dafür gibt es eine, wenn auch weitaus kompliziertere Anwendung, des PHP-Interpreters per CGI und zwar Fast-CGI.
Ich möchte kurz auf die Installation von Apache2 mit dem worker-Modul und php5 unter Debian eingehen. Nicht beachten bzw. weiter eingehen werde ich hierbei Sicherheitsaspekte wie getrennte User-Rechte. Da ich im Grunde Server betreue, welche nur von EINEM realen Benutzer verwendet werden, ist dies für mich bisher auch nicht nötig gewesen. Ergänzende Informationen dazu findet man bei Google 😉
Beginnen wir mit der Installation des Moduls
apt-get install apache2 apache2-mpm-worker libapache2-mod-fcgid
Wer hierbei bereits Apache prefork mit mod_php5 installiert hatte, wird feststellen, dass APT neben dem prefork-Modul auch php5 komplett entfernt. Dies kann im Anschluss mit
apt-get install php5-cgi php5
rückgängig gemacht werden. Nun ist Apache im Grunde bereits mit dem schnellen Modul ausgestattet, leider laufen keine php-Anwendungen mehr. Also wird an dieser Stelle nun das ebenfalls mit installierte FastCGI-Modul konfiguriert. So passen wir ggf. /etc/apache/mods-enabled/fcgid.conf an.
AddHandler fcgid-script .fcgi SocketPath /var/lib/apache2/fcgid/sock IPCConnectTimeout 20
Es folgt die Konfiguration der einzelene VHosts oder global der apache2.conf. Hierfür wird dem directory-Abschnitt folgende Zeilen hinzugefügt
AddHandler fcgid-script .php FCGIWrapper /usr/lib/cgi-bin/php5 .php Options ExecCGI
Man erahnt vielleicht, dass an dieser Stelle möglich ist, verschiedene Versionen von PHP zu verwenden. Die Sache erfüllt bereits ihren Zweck, und eine Test.php-Datei mit folgendem Inhalt zeigt dies auch an
< ? php phpinfo(); ?>
Als ich mit AB die Performance testete, stieg die Anzahl der PHP-Prozesse wie erwartet an. Ab einer gewissen Anzahl jedoch wurden keine neuen erzeugt. Es scheint, als muss dieses Verhalten ebenso dem Interpreter übergeben werden. Die geschieht, wie ich finde, umständlich über ein Skript, welches die maximale Anzahl der neu zu forkenden PHP-Prozesse und die maximalen Anfragen pro PHP-Prozess im System bekannt macht. /etc/php5/php-procs.sh (ausführbarmachen nicht vergessen).
#!/bin/sh PHP_FCGI_CHILDREN=2 PHP_FCGI_MAX_REQUESTS=100 export PHP_FCGI_CHILDREN export PHP_FCGI_MAX_REQUESTS exec /usr/lib/cgi-bin/php5
Nun noch den Wrapper weiter oben auf das neue Skript leiten, statt direkt auf das php-Binary
FCGIWrapper /etc/php5/php-procs.sh .php
Diese Werte können angepasst werden, und ändern die Zeitspanne, wie schnell wieviele Prozesse erzeugt werden, hier ist ausprobieren angesagt. Mehr als ca. 300 Prozesse werden anscheinend nicht erstellt, wo diese Einstellung zu finden ist, fände ich interessant.
Letztlich bleibt zu sagen, dass auf meiner 4-Kern-4-Gigabyte-RAM-Testkiste beeindruckende 1.500 Requests/Sekunde für Abrufen der test.php und weit über 10.000 Request/Sekunde für das normale Abrufen einer 100 Byte Testdatei. Da kann wohl kein prefork mehr mithalten…
7 Gedanken zu „worker vs. prefork mit PHP“
Hi Marco,
schöne Idee – gute Beschreibung – und wäre toll, wenn man so einen „hochperformanten“ Indianer bauen könnte.
Wenn ich allerdings nach der Apache2-Installation (wie oben apt-get install apache2 apache2-mpm-worker libapache2-mod-fcgid) nun PHP5 (apt-get install php5) installieren möchte, will APT sofort den worker wieder entfernen und prefork nachinstallieren.
Kennst du das, bzw. wie schafft man Abhilfe?
Ich teste das mal in einer VM, das war noch zu ETCHs Zeiten, jetzt ist ja LENNY dran…
EDIT: Bitte probiere statt „apt-get install php5“ „apt-get install php5-cgi“
Sonst wird wohl immer das Apache-Modul installiert, wir wollen aber das cgi-Modul – mein Fehler.
Das hat geklappt (auf lenny, ja) – php5-cgi installieren, somit funktioniert es wunderbar. Vielen Dank!
Ja, war wohl unter Etch genauso, war also mein Fehler 😉
Hallo Marko,
deine Anleitung funktioniert … prima und Lob.
Leider scheint mein Ajax Framework mit dem fcgi php5 nicht mehr zu laufen, deshalb habe ich soeben mit dem Experiment abgebrochen (keine Lust zu debuggen)
Worum es mir geht?
Hast du eine Ahnung bzw. fundiertes Wissen bezüglich der Performance des FCGI PHP5 Workers in Bezug auf riesige Datenmengen?
Ich arbeite derzeit an einer Auswertungssoftware, die aus einer Datenbank mit derzeit 80 Mio Zeilen Auswertungen erstellt.
Derzeit liege ist die Software bei einem größeren Zeitraum recht schlaff. PHP (trotz Optimierungen im Indianer) braucht derzeit ca.:
MySQL-Query´s: 112.378 s / PHP: 410.672 s
Das ist schon ganz schön lang 🙁 … das ganze läuft aktuell auf einem Core i7 950 Server mit 8GB RAM und 3x300GB WD Hardware Raid mit dem Ubuntu 9.10 64 Bit Server.
Also an der Hardware liegts sicher nicht 😉
Hast du eine Ahnung, ob mich hier der Worker beflügelt?
Bitte antworte auch per Email … dank im Voraus.
Da es sehr spezielle Fragen sind, habe ich dir mal per Mail geantwortet 😉
Cooles Tutorial, hat mir weiter geholfen. Danke. Kannst du vielleicht richtige Vergleichstabellen für die Performance-Unterschiede bereitsstellen, hätte ich zur Anschauung noch besser gefunden?