Sie befinden sich hier

Inhalt

Optimierung von PHP und Apache auf Debian-Linux - viele Informationen mit wenig Gehalt

Das Zuammenspiel von Apache mit "größeren" PHP-basierten Anwendungen wie beispielsweise Typo3 verlangt in der Regel viel Geduld - vom Nutzer, wenn der Server schlecht konfiguriert ist, und vom Administrator, wenn er seinen Server optimieren wlil. Im Netz schwirrt eine ganze Menge an "Tutorials" und "Howtos" umher, die aber oft viel zu kompliziert sind und nicht erklären, warum eigentlich welcher Schritt erforderlich ist.

Im folgenden möchte ich meine Erfahrungen zusammenfassen, die ich mit Apache 2.x und PHP unter Debian bisher gesammelt habe (und sicher noch sammeln werde...). Hierbei wird kein Anspruch auf Vollständigkeit erhoben, sondern es soll vielmehr ein möglichst reproduzierbarer und "debiankonformer" Weg gezeigt werden, die Leistung von Apache mit PHP zu verbessern und das Hintergrundwissen über die Varianten zu erweitern.

Möglichkeiten der PHP-Nutzung mit Apache

1.) mod_php

Die einfachste Möglichkeit, PHP-Anwendungen mit Apache zu betreiben, ist das Modul "mod_php". Es stellt eine Laufzeit-Bibliothek dar, die direkt in den Apache-Prozeß geladen und mit ihm ausgeführt wird. Aus diesem Grund bietet dieser Weg theoretisch die höchste Verarbeitungsgeschwindigkeit (welche mit zusätzlichem Cache wie z.B. APC noch erhöht werden kann), aber auch die meisten Einschränkungen:

  • es sollte nur mit threadingfreiem Apache (mpm-prefork) benutzt werden, um Multithreading-Probleme mit PHP-Applikationen zu verhindern (Info von PHP.net)
  • alle PHP-Operationen werden mit den Rechten des Apache-Prozesses ausgeführt, unter Debian ist das der Benutzer "www-data" - somit ist diese Variante nur für Applikationen geeignet, die direkt dem Serverinhaber unterstehen, wie z.B. Webmail-Dienste o.ä., aber nicht für Internetpräsenzen mehrerer Nutzer, welche diese mit ihren Rechten selbst verwalten können sollen

2.) suphp

Das Modul suphp ermöglicht, die beiden genannten Probleme zulasten des Hauptvorteils von mod_php - der Geschwindigkeit - zu lösen. Dieses Modul führt jede PHP-Datei mit den Benutzerrechten ihres Eigentümers aus, wofür es für jede einzelne Anfrage (!) die PHP-Laufzeitumgebung einzeln startet. Mit dieser Eigenschaft sollte die Benutzbarkeit mit threadingbehafteten Apache-Varianten möglich sein (selbst habe ich jedoch nur "prefork" genutzt) - aber genau hierdurch geht auch jede Geschwindigkeit verloren. Als Beispiel: meine eigene Seite hatte mit dieser Konfiguration eine Haupt-Auslieferungslatenz gemäß Google PageSpeed von 1,4 Sekunden. Aufgrund der anfragespezifischen Ausführung und Beendigung der PHP-Umgebung ist in diesem Fall auch keine Optimierung durch Cache-Erweiterungen wie APC möglich.

3.) php5_cgi

Das Debian-Paket "php5_cgi" bringt alles mit, um die Ausführung von PHP über die CGI-Schnittstelle von Apache zu erlauben. CGI ist ohnehin die einzig relevante Alternative zu den vorgenannten "Direkt-Modulen", die eine Lösung aller genannten Probleme sein könnte. Um es vorwegzunehmen: sie ist es, wenn bestimmte Randbedingungen beachtet bzw. angepaßt werden.

4.) Mein Lösungsweg mit php5_cgi, mod_fcgid und, wo nötig, mod_suexec und apache2-suexec-custom

4.1 Ausgangslage

Nun ist CGI allerdings für eine gewisse Langsamkeit in der Ausführung bekannt, und in praktisch allen "Tutorials" ist etwas von FastCGI zu lesen, was (im Falle von PHP) die Geschwindigkeit praktisch auf das Niveau der "nativen" PHP-Interpretation mit mod_php heben soll. Verfolgt man diese Beschreibungen weiter, wird in der Regel sehr viel auf kompliziertem Wege (und an verschiedensten Stellen) konfiguriert, zudem wird immer davon ausgegangen, daß mod_suexec zwingend verwendet werden soll. Dieses Modul ist aber nur erforderlich, wenn der Anwendungsfall von suphp mit abgedeckt werden soll, daß Skripte unter den Rechten eines bestimmten Benutzers laufen sollen.

4.2 Analyse der vorgegebenen Möglichkeiten

Ein genaues Betrachten der Konfigurationsdateien php5_cgi.conf und fcgid.conf (in /etc/apache/mods-available) sowie den Informationen zum Stichwort "Handler" (AddHandler, SetHandler und Action) zeigt, daß eigentlich alles für eine Kombination von PHP, CGI und FastCGI (mit fcgid) vorhanden ist und nur wenig geändert werden muß:

  • fcgid ist standardmäßig so konfiguriert, daß es alle Dateien mit der Endung ".fcgi" als FastCGI ausführt
  • php5_cgi hat eine auskommentierte Standardkonfiguration am Ende von php5_cgi.conf, die alle PHP-Dateien per (normalem) CGI an PHP übergibt - wird diese einkommentiert, funktioniert PHP per CGI sofort:

ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory "/usr/lib/cgi-bin">
    AllowOverride None
    Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
    Order allow,deny
    Allow from all
</Directory>
Action application/x-httpd-php /cgi-bin/php5

4.3 Zusammenführung der Erkenntnisse zu lauffähigem FastCGI mit PHP

Was ist zu tun, um die beiden Erkenntnisse zu kombinieren? Ganz einfach: es muß eine Anwendung definiert werden, die als Endung ".fcgi" besitzt! Dazu wird lediglich im Verzeichnis /usr/lib/cgi-bin ein symbolischer Link von php5 auf php5.fcgi erstellt und die Konfiguration von php5_cgi folgendermaßen geändert:

ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory "/usr/lib/cgi-bin">
    AllowOverride None
    Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
    Order allow,deny
    Allow from all
</Directory>
# Standard CGI or FastCGI?
#Action application/x-httpd-php /cgi-bin/php5
Action application/x-httpd-php /cgi-bin/php5.fcgi

Fertig! Nun müssen noch die korrekten Module aktiviert und die falschen deaktiviert werden:

a2enmod php5_cgi, a2enmod fcgid

a2dismod php5, a2dismod suphp

...und zuguterletzt wird der Apache neu gestartet und ein PHP per FastCGI (mit Modul fcgid) sollte rudimentär laufen!

Sofern ich die Zeit finde, werde ich neben dem Modul "fcgid" auch noch versuchen, dieselbe Konfiguration an das originale Modul "fastcgi" zu adaptieren, falls dies möglich ist.

4.4 Anpassung der Einstellungen/Überwachungen von fcgid für höhere Anforderungen

Es empfiehlt sich, die gesamte Liste der Optionen von mod_fcgid durchzugehen und zu prüfen, welche Änderungen für die jeweilige Anwendung sinnvoll sind. Da ich auf einem System Applikationen einsetze, die größere Uploads und längere Verarbeitungen "verdauen" müsen, habe ich folgende Ergänzungen (fett markiert und kommentiert) in die fcgid.conf eingefügt:

<IfModule mod_fcgid.c>
  AddHandler    fcgid-script .fcgi
  FcgidConnectTimeout 20

  # erlaube lange Skriptaufzeiten von 90 Minuten
  FcgidBusyTimeout 5400
 
# erlaube eine Verzögerung der Skript-Erstantwort von 10 Minuten
  FcgidIOTimeout 600

  # übernehme die Einstellung aus /etc/php5/cgi/php.ini
  FcgidFixPathinfo 1
  # setze die von PHP gesteuerte Prozeß-Lebenszeit recht hoch
  FcgidInitialEnv PHP_FCGI_MAX_REQUESTS 10000
  # setze denselben Wert innerhalb fcgid, um keinen Error 500 zu bekommen
  FcgidMaxRequestsPerProcess 10000
  # erlaube die Mindestanzahl an Prozessen dauerhaft aktiv zu halten
  FcgidProcessLifeTime 0
  # erlaube 800 MB Uploads
  FcgidMaxRequestLen 838860800
  # verdopple den maximalen RAM-Puffer pro Anfrage
  FcgidMaxRequestInMem 131072
  # verdopple die Datenhäppchen-Größe, wegen der eine Übermittlung an den Client erzwungen wird
  FcgidOutputBufferSize 131072
</IfModule>

4.5 Erweiterung dieser Konfiguration um suexec

Diese Ergänzung folgt demnächst!

Kommentare, Anregungen, Ergänzungen?

Keine Kommentare
Kommentar hinzufügen

* - Pflichtfeld

*

*


*

Kontextspalte