KeyHelp: PHP-FPM-Prozessmanager je Kunde wählen und pm.max_children einstellen
So wählen Sie in KeyHelp je Kunde static, ondemand oder dynamic, stellen pm.max_children ein und messen mit ab, Prozessliste, FPM-Log und Statusseite, wie sich der Pool unter Last wirklich verhält.
Geprüft am 01.10.2026 · für KeyHelp 26.1.1
Mit KI erstellt – redaktionelle Prüfung ausstehend
WerbelinksMit * markierte Links sind Werbelinks: Bei einem Kauf erhalten wir eine Provision, der Preis bleibt gleich. Als Amazon-Partner verdiene ich an qualifizierten Verkäufen. Mehr dazu

Wie viele Anfragen eine Website gleichzeitig verarbeiten kann, entscheidet bei KeyHelp der PHP-FPM-Pool des Kunden. Steht pm.max_children zu niedrig, warten Besucher in der Schlange, steht es zu hoch, belegen die Prozesse eines Kunden unter Last entsprechend viel Arbeitsspeicher. KeyHelp lässt Sie den Prozessmanager und die Grenzen je Kunde wählen. Diese Anleitung zeigt die drei Modi static, ondemand und dynamic, was KeyHelp daraus in die Pool-Datei schreibt und wie sich jeder Modus unter Last tatsächlich verhält, gemessen mit ab und der FPM-Statusseite. Sie richtet sich an Administratoren eines Servers wie in KeyHelp installieren und absichern. Die allgemeine Dimensionierung für WordPress beschreibt die Anleitung PHP-FPM-Pools für WordPress richtig dimensionieren. Getestet haben wir mit KeyHelp 26.1.1 und PHP 8.2 auf Debian 12.
Voraussetzungen
- Ein KeyHelp-Server mit Administrator-Zugang. Getestet mit KeyHelp 26.1.1 (Build 3698) auf Debian 12.15 mit PHP 8.2, 2 CPU-Kerne, 4 GB RAM.
- Ein Kundenkonto mit PHP, im Beispiel
kunde1mitkunde1.example.de. - SSH-Zugang als root für Pool-Datei, Prozessliste und Lasttest. Das Werkzeug
ab(ApacheBench) war auf dem Testserver bereits vorhanden.
Schritt 1: Ausgangslage und Lasttest im Grundzustand
Die Pool-Datei des Kunden liegt in /etc/php/8.2/fpm/pool.keyhelp.d/kunde1.conf. Im Grundzustand steht dort:
pm = ondemand
pm.max_children = 3
pm.max_requests = 0
pm.process_idle_timeout = 10s
Für einen nachvollziehbaren Test haben wir im Webspace ein Skript abgelegt, das zwei Sekunden wartet und dann seine Prozess-ID ausgibt. Es simuliert eine langsame Seite, etwa eine aufwendige Datenbankabfrage:
echo '<?php usleep(2000000); echo getmypid(), "\n";' > /home/users/kunde1/www/slow.php
chown kunde1:kunde1 /home/users/kunde1/www/slow.php
ab -n 20 -c 10 -H "Host: kunde1.example.de" http://127.0.0.1/slow.php
Time taken for tests: 16.014 seconds
Complete requests: 20
Failed requests: 0
Requests per second: 1.25 [#/sec] (mean)
Time per request: 8007.029 [ms] (mean)
Zwanzig Anfragen zu je zwei Sekunden brauchten 16 Sekunden, weil nie mehr als drei gleichzeitig liefen. Im Mittel wartete jede Anfrage 8 Sekunden statt 2. Keine Anfrage schlug fehl, die übrigen standen in der Warteschlange. Im FPM-Log /var/log/php8.2-fpm.log stand danach:
[01-Oct-2026 17:55:55] WARNING: [pool kunde1] server reached max_children setting (3), consider raising it
Bei der nächsten Abfrage, rund 15 Sekunden nach Testende, lief kein einziger Prozess des Pools mehr. Das ist ondemand: Prozesse entstehen bei Bedarf und enden laut PHP-Dokumentation nach pm.process_idle_timeout, hier 10 Sekunden.
Verifizieren: grep max_children /var/log/php8.2-fpm.log zeigt, ob ein Pool schon an seine Grenze gestoßen ist. Taucht der Kunde dort regelmäßig auf, ist pm.max_children zu knapp.
Schritt 2: Den Reiter „PHP-FPM“ verstehen
Öffnen Sie „Benutzerverwaltung“, „Kundenkonten“, den Kunden bearbeiten und den Reiter „PHP-FPM“. Unter „pm“ stehen drei Modi, die Oberfläche beschreibt sie so:
- static: „Die Anzahl der Kindprozesse ist festgelegt (pm.max_children).“ Alle Prozesse laufen dauerhaft.
- ondemand: „Die Kindprozesse werden gestartet, sobald sie benötigt werden.“
- dynamic: „Die Anzahl der Kindprozesse wird dynamisch angepasst.“ Hier blendet KeyHelp zusätzlich pm.min_spare_servers und pm.max_spare_servers ein.
Für alle Modi gelten pm.max_children („Die maximale Anzahl an Kindprozessen, die erstellt werden können.“) und pm.max_requests (Anfragen je Prozess bis zum Neustart, 0 für unbegrenzt). pm.start_servers ist bei dynamic kein Eingabefeld, KeyHelp berechnet es nach der angezeigten Formel pm.min_spare_servers + (pm.max_spare_servers - pm.min_spare_servers) / 2.

Verifizieren: Beim Wechsel auf dynamic erscheinen die Felder pm.min_spare_servers und pm.max_spare_servers sowie die Formel für pm.start_servers.
Schritt 3: dynamic einstellen und messen
Wir haben dynamic mit pm.max_children 8, pm.max_requests 500, pm.min_spare_servers 2 und pm.max_spare_servers 4 gespeichert. Die Meldung: „Der Benutzer kunde1 wurde aktualisiert. Die Änderungen werden in wenigen Augenblicken wirksam.“ Etwa eine Minute später stand in der Pool-Datei:
pm = dynamic
pm.max_children = 8
pm.max_requests = 500
pm.process_idle_timeout = 10s
; Following pm.* options are only used, when 'pm = dynamic'
pm.start_servers = 3
pm.min_spare_servers = 2
pm.max_spare_servers = 4
Nach dem Neuladen von PHP-FPM liefen ohne jede Anfrage drei Prozesse, genau pm.start_servers. Dann der Lasttest mit 40 Anfragen bei 12 gleichzeitigen Verbindungen. In einem zweiten Lauf mit denselben Werten haben wir die Prozesszahl parallel sekündlich gezählt:
s1: 4 Prozesse
s2: 4 Prozesse
s3: 7 Prozesse
s4: 8 Prozesse
s5: 8 Prozesse
Time taken for tests: 14.007 seconds
Complete requests: 40
Failed requests: 0
Requests per second: 2.86 [#/sec] (mean)
PHP-FPM startete die Prozesse in Schüben bis zur Grenze von 8. Da 12 Verbindungen auf 8 Prozesse trafen, meldete das Log beim ersten Lauf wieder die Grenze, diesmal mit dem Namen des Parameters:
[01-Oct-2026 17:59:01] WARNING: [pool kunde1] server reached pm.max_children setting (8), consider raising it
Fünfzehn Sekunden nach der Last liefen noch vier Prozesse, also pm.max_spare_servers. Jeder belegte nach dem zweiten Lauf im Leerlauf rund 24 MB (RSS in KB):
24524 php-fpm: pool kunde1
24520 php-fpm: pool kunde1
Verifizieren: ps -u kunde1 -o args= | grep -c "pool kunde1" liefert im Leerlauf einen Wert zwischen pm.min_spare_servers und pm.max_spare_servers und unter Last höchstens pm.max_children.
Schritt 4: static und die Statusseite
Zum Vergleich haben wir static mit pm.max_children 5 gesetzt und im selben Reiter „Statusseite aktivieren“ angehakt. Ins Feld „Beschränken Sie den Zugriff auf folgende IP (leer = keine Einschränkung)“ kam 127.0.0.1.

In der Pool-Datei ergänzt KeyHelp dafür pm.status_path = /fpm-status und ping.path = /fpm-ping, im Apache-vHost des Kunden einen eigenen Block:
<LocationMatch "/(fpm-ping|fpm-status)">
SetHandler "proxy:unix:/run/php/keyhelp_kunde1.socket|fcgi://kunde1.server.example.de"
Require ip 127.0.0.1
</LocationMatch>
Ein Abruf auf dem Server selbst, aber über seine Netzwerkadresse statt über 127.0.0.1, lieferte HTTP 403, lokal antwortet /fpm-ping mit pong und /fpm-status mit den Zählern des Pools. Im Leerlauf liefen bei static fünf Prozesse, ohne dass eine Anfrage kam. Nach 20 Anfragen bei 10 gleichzeitigen Verbindungen zeigte die Statusseite:
curl -s --resolve kunde1.example.de:80:127.0.0.1 http://kunde1.example.de/fpm-status | grep -E "max listen queue|max active|max children reached"
max listen queue: 0
max active processes: 5
max children reached: 0
Der Test dauerte 10 Sekunden. Auffällig: Obwohl alle fünf Prozesse belegt waren und Anfragen warten mussten, blieb „max children reached“ bei 0, und im FPM-Log erschien keine neue Warnung. Bei static lesen Sie die Auslastung deshalb besser an „max active processes“ und an der Antwortzeit ab als an der Warnung.
Verifizieren: curl -s --resolve kunde1.example.de:80:127.0.0.1 http://kunde1.example.de/fpm-ping auf dem Server liefert pong, derselbe Abruf über die Netzwerkadresse des Servers liefert 403.
Schritt 5: Den passenden Modus wählen
Die Messungen zeigen den Unterschied im Leerlauf: Bei ondemand lief kein Prozess, bei dynamic liefen zwischen pm.min_spare_servers und pm.max_spare_servers Prozesse (3 nach dem Neuladen, 4 nach der Last), bei static dauerhaft alle fünf. Unter Last wuchsen ondemand und dynamic bis pm.max_children. ondemand belegt im Leerlauf also den wenigsten Arbeitsspeicher, static den meisten.
Für pm.max_children zählt der Arbeitsspeicher: Jeder Prozess belegt eigenen Speicher, im Test mit dem Zwei-Sekunden-Skript rund 24 MB im Leerlauf. Eine echte Anwendung braucht mehr. Messen Sie den tatsächlichen Verbrauch Ihrer Anwendung unter Last mit ps -u KUNDE -o rss=,args= und vergleichen Sie ihn mit dem verfügbaren Speicher des Servers, für alle Kunden zusammen.
Verifizieren: free -m zeigt in der Spalte „available“ den verfügbaren Speicher, auf dem Testserver vor den Tests 2070 MB bei 3895 MB gesamt. Taucht der Kunde im Betrieb weiter mit „server reached“ im FPM-Log auf, ist pm.max_children noch zu knapp.
Typische Fehler
Spare-Werte vertauscht
Mit pm.min_spare_servers 6 und pm.max_spare_servers 3 lehnt KeyHelp das Speichern ab: „Der Wert von pm.min_spare_servers darf nicht größer als pm.max_spare_servers sein.“
Spare-Werte größer als max_children
Mit pm.max_children 4 und pm.max_spare_servers 6 lautet die Meldung: „Die Werte von pm.min_spare_servers und pm.max_spare_servers dürfen nicht größer als pm.max_children sein.“
pm.max_children 0
Das Feld erlaubt im Browser nur Werte ab 1. Wird die Browserprüfung umgangen, meldet KeyHelp: „Ungültige Angabe im PHP-FPM-Einstellungs-Feld pm.max_children.“
Statusseite ohne IP-Beschränkung
Bleibt das IP-Feld leer, gibt es laut Beschriftung keine Einschränkung. Die Statusseite zeigt Poolname, Startzeit und Auslastung (siehe Schritt 4) und wäre dann für jeden abrufbar. Getestet haben wir nur die beschränkte Variante. Tragen Sie eine IP ein, etwa die Ihres Monitorings.
Warnung fehlt trotz Engpass
Wie in Schritt 4 gemessen, schrieb static im Test bei vollem Pool keine Warnung „server reached“. Wer nur das Log überwacht, übersieht den Engpass.
Häufige Fragen
Kann ich pm.process_idle_timeout ändern?
Im Reiter „PHP-FPM“ gibt es dafür kein Feld. In allen drei Modi schrieb KeyHelp pm.process_idle_timeout = 10s in die Pool-Datei. Wirksam ist der Wert laut PHP-Dokumentation nur bei ondemand.
Wann wirkt die Änderung?
Im Test innerhalb einer Minute nach dem Speichern. Danach liefen neu gestartete Prozesse des Pools, KeyHelp lädt PHP-FPM also neu. Ob laufende Anfragen beim Neuladen abbrechen, haben wir nicht gezielt geprüft.
Wofür ist pm.max_requests gut?
Ein Prozess wird nach dieser Anzahl von Anfragen neu gestartet. Laut PHP-Dokumentation hilft das, Speicherlecks in Bibliotheken von Drittanbietern zu umgehen. Im Grundzustand steht 0 für unbegrenzt, im Test mit dynamic haben wir 500 gesetzt.
Darf der Kunde den Modus selbst ändern?
Der Reiter „PHP-FPM“ ist Teil der Kontoeinstellungen des Administrators. Ob es eine Berechtigung für Kunden gibt, haben wir nicht geprüft.
Testumfang
Wir haben auf KeyHelp 26.1.1 mit PHP 8.2 alle drei Modi für einen Kunden gesetzt, die Pool-Datei geprüft und jeden Modus mit ab und einem Zwei-Sekunden-Skript belastet, Prozesszahl, Log und Statusseite gemessen. Auffällig: Ab Werk reichen drei Prozesse, und static meldet einen vollen Pool nicht im Log. Echte Anwendungen, Speichergrenzen unter Last und mehrere Kunden gleichzeitig haben wir nicht getestet. Messen Sie mit Ihrer eigenen Anwendung nach.
Fazit
Der Grundwert von drei Prozessen führte im Test schon bei zehn gleichzeitigen Anfragen zur Warteschlange. Mit dem Reiter „PHP-FPM“ passen Sie das je Kunde an, KeyHelp prüft dabei die Spare-Werte und berechnet start_servers selbst. Entscheidend ist, die Wirkung zu messen: Prozesszahl mit ps, Engpässe im FPM-Log und über die auf eine IP beschränkte Statusseite. So finden Sie für jeden Kunden einen Wert, der Besucher nicht warten lässt und den Arbeitsspeicher des Servers nicht überfordert.
Weiterführende Anleitungen und Quellen
- KeyHelp installieren und absichern
- PHP-FPM-Pools für WordPress richtig dimensionieren: pm.max_children
- WordPress-Hosting-Ressourcen prüfen: PHP-Worker und Arbeitsspeicher
- Keyweb: KeyHelp, alle Funktionen im Überblick
- PHP-Handbuch: FPM-Konfiguration (pm, pm.max_children, pm.status_path)
- Apache: ab, das Benchmark-Werkzeug


