Seit einer halben Ewigkeit setzen wir nun schon auf FastCGI wenn es darum geht PHP-Skripte auszuführen. Zum einen haben wir dadurch mehr Kontrolle über das, was jeder Kunde macht bzw. machen darf, zum anderen ist das natürlich ein großer Vorteil in Sachen Sicherheit, da jeder Skript unter der Benutzer-ID des Kunden direkt ausgeführt wird.
An und für sich hat PHP eine sehr schöne FastCGI-Implementierung, was ein (weiterer) großer Vorteil gegenüber Perl, Python oder Ruby ist. Auf der anderen Seite hat es auch ein paar Macken. Ganz gefährlich ist z.B. die Einstellung "PHP_FCGI_MAX_REQUESTS", die sich recht wenig mit mod_fcgid versteht - so fährt PHP nach n Anfragen den Interpreter runter, beendet sich selbst aber nicht, sodass neue Anfragen in den ersten Tagen schon mal ins Leere liefen.
So eine andere Einstellung, die der PHP im FastCGI-Modus bietet ist "PHP_FCGI_CHILDREN", die PHP veranlasst bis zu n Unterprozesse zu starten, sodass der FastCGI-Server im Prinzip zu einem vollständigen preforked Server wird. Wenn man überlegt, dass PHP gerne Arbeitsspeicher isst, ohne ihn danach wieder freizugeben, eigentlich eine gute Möglichkeit um das ein wenig einzugrenzen.
Da bei uns das allerdings vom Webserver an sich reguliert wird, haben wir die Einstellung auf "1" gesetzt, d.h. PHP durfte maximal einen Kindprozess erstellen - was es auch brav getan hat, nur klingt es ein wenig unlogisch, den Interpreter zu starten, einen Kindprozess zu forken und dann die Anfrage mit zwei Prozessen zu verarbeiten...
Von schlauer Software würde ich so etwas wie "ich habe nur einen Kindprozess, da kann ich mir den fork sparen" erwarten, sodass ich mich eben endlich mal an den PHP-Source-Code gewagt habe um diese Funktion einzupflegen.
Doch siehe da: PHP ist bereits fast so schlau, denn wird "PHP_FCGI_CHILDREN" nicht angegeben, führt PHP gar keinen fork aus...
Leider ist dieses Verhalten (bzw. die FastCGI-Schnittstelle) ganz schlecht dokumentiert und auch die FastCGI-Readme lässt anders vermuten:
PHP_FCGI_CHILDREN (default value: 8 )
This controls how many child processes the PHP process spawns. When the fastcgi starts, it creates a number of child processes which handle one page request at a time. So by default, you will be able to handle 8 concurrent PHP page requests. Further requests will be queued.
Increasing this number will allow for better concurrency, especially if you have pages that take a significant time to create, or supply a lot of data (e.g. downloading huge files via PHP). On the other hand, having more processes running will use more RAM, and letting too many PHP pages be generated concurrently will mean that each request will be slow.
Schön, dass ich es nun besser weiß
Eine letzte Anmerkung zur Überschrift: Will man also nur einen Kindprozess haben, ist es sinnvoller den Fork ganz zu unterbinden, d.h. die Einstellung gar nicht zu setzen. Das spart letzten endes noch das eine oder andere Byte wertvollen Arbeitsspeicher