NGINX 502 Bad Gateway: PHP-FPM
Anmerkung des Herausgebers: php-fpm verwendet den Begriff „Master“, um seinen primären Prozess zu beschreiben. Datadog verwendet diesen Begriff nicht. In diesem Blogbeitrag werden wir dies als „primär“ bezeichnen, außer aus Gründen der Klarheit in Fällen, in denen wir auf einen bestimmten Prozessnamen verweisen müssen.
Dieser Beitrag ist Teil einer Serie zur Fehlerbehebung bei NGINX 502 Bad Gateway-Fehlern. Wenn Sie PHP-FPM nicht verwenden, lesen Sie unseren anderen Artikel zur Fehlerbehebung bei NGINX 502 mit Gunicorn als Backend.
PHP-FastCGI Process Manager (PHP-FPM) ist ein Daemon für die Verarbeitung von Webserver-Anfragen für PHP-Anwendungen. In der Produktion wird PHP-FPM häufig hinter einem NGINX-Webserver bereitgestellt. NGINX Proxies Web-Anfragen und leitet sie an PHP-FPM Worker-Prozesse, die die PHP-Anwendung ausführen.
NGINX gibt einen 502 Bad Gateway-Fehler zurück, wenn es eine Anfrage nicht erfolgreich an PHP-FPM weiterleiten kann oder wenn PHP-FPM nicht antwortet. In diesem Beitrag untersuchen wir einige häufige Ursachen für 502-Fehler im NGINX / PHP-FPM-Stack und geben Anleitungen, wo Sie Informationen finden, die Ihnen bei der Behebung dieser Fehler helfen können.
Untersuchen Sie die Metriken, Protokolle und Spuren hinter NGINX 502 Bad Gateway-Fehlern mithilfe von Datadog.
Einige mögliche Ursachen für 502s
In diesem Abschnitt beschreiben wir, wie die folgenden Bedingungen dazu führen können, dass NGINX einen 502-Fehler zurückgibt:
- PHP-FPM läuft nicht
- NGINX kann nicht mit PHP-FPM kommunizieren
- PHP-FPM läuft ab
PHP-FPM Aus einem dieser Gründe wird es mit einem 502-Fehler antworten und dies in seinem Zugriffsprotokoll (/ var/log/ nginx/access.log), wie in diesem Beispiel gezeigt:
Zugriff.log
127.0.0.1 - - "GET / HTTP/1.1" 502 182 "-" "curl/7.58.0"
Das NGINX-Zugriffsprotokoll erklärt nicht die Ursache eines 502-Fehlers, aber Sie können das Fehlerprotokoll (/var/log/nginx/error.log), um mehr zu erfahren. Zum Beispiel ist hier ein entsprechender Eintrag im NGINX-Fehlerprotokoll, der zeigt, dass die Ursache des 502-Fehlers darin besteht, dass der Socket nicht existiert, möglicherweise weil PHP-FPM nicht ausgeführt wird. (Im nächsten Abschnitt erfahren Sie, wie Sie dieses Problem erkennen und beheben können.)
Fehler.log
2020/01/31 18:30:55 13617#13617: *557 connect() to unix:/run/php/php7.2-fpm.sock failed (2: No such file or directory) while connecting to upstream, client: 127.0.0.1, server: localhost, request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/run/php/php7.2-fpm.sock:", host: "localhost"
PHP-FPM läuft nicht
Hinweis: Dieser Abschnitt enthält einen Prozessnamen, der den Begriff „master“ verwendet.“ Außer in Bezug auf bestimmte Prozesse verwendet dieser Artikel stattdessen den Begriff „Primär“.
Wenn PHP-FPM nicht ausgeführt wird, gibt NGINX einen 502-Fehler für jede Anforderung zurück, die die PHP-Anwendung erreichen soll. Wenn Sie 502s sehen, überprüfen Sie zuerst, ob PHP-FPM ausgeführt wird. Auf einem Linux-Host können Sie beispielsweise einen ps
-Befehl wie diesen verwenden, um nach laufenden PHP-FPM-Prozessen zu suchen:
sudo ps aux | grep 'php'
PHP-FPM organisiert seine Arbeitsprozesse in Gruppen, die als Pools bezeichnet werden. Die folgende Beispielausgabe zeigt, dass der primäre PHP-FPM-Prozess ausgeführt wird, ebenso wie zwei Arbeitsprozesse im Standardpool (mit dem Namen www
):
root 29852 0.0 2.2 435484 22396 ? Ssl 16:27 0:00 php-fpm: master process (/etc/php/7.2/fpm/php-fpm.conf)www-data 29873 0.0 1.5 438112 15220 ? Sl 16:27 0:00 php-fpm: pool wwwwww-data 29874 0.0 1.6 438112 16976 ? Sl 16:27 0:00 php-fpm: pool www
Wenn die Ausgabe des Befehls ps
keine PHP-FPM-Primär- oder Poolprozesse anzeigt, müssen Sie PHP-FPM zum Laufen bringen, um die 502-Fehler zu beheben.
In einer Produktionsumgebung sollten Sie systemd verwenden, um PHP-FPM als Dienst auszuführen. Dies kann Ihre PHP-Anwendung zuverlässiger und skalierbarer machen, da der PHP-FPM-Daemon Ihre PHP-App automatisch bereitstellt, wenn Ihr Server gestartet wird oder wenn eine neue Instanz gestartet wird. PHP-FPM ist im PHP-Quellcode enthalten, sodass Sie PHP-FPM als Systemd-Dienst hinzufügen können, wenn Sie PHP konfigurieren.
Sobald Ihr PHP-FPM-Projekt als Dienst konfiguriert ist, können Sie mit dem folgenden Befehl sicherstellen, dass es beim Start Ihres Servers automatisch gestartet wird:
sudo systemctl enable php7.2-fpm.service
Anschließend können Sie den Befehl list-unit-files
verwenden, um Informationen zu ihr Service:
sudo systemctl list-unit-files | grep -E 'php*fpm'
Auf einem PHP 7.2 server, auf dem PHP-FPM installiert ist (auch wenn es nicht ausgeführt wird), lautet die Ausgabe dieses Befehls:
php7.2-fpm.service enabled
Verwenden Sie diesen Befehl, um Informationen zu Ihrem PHP-FPM-Dienst anzuzeigen:
sudo systemctl is-active php7.2-fpm.service
Dieser Befehl sollte eine Ausgabe von active
. Wenn dies nicht der Fall ist, können Sie den Dienst mit starten:
sudo service php7.2-fpm start
NGINX kann nicht auf den Socket zugreifen
Wenn PHP-FPM startet, erstellt es einen oder mehrere TCP- oder Unix-Sockets, um mit dem NGINX-Webserver zu kommunizieren. Die Worker-Prozesse von PHP-FPM verwenden diese Sockets, um auf Anforderungen von NGINX zu warten.
Um festzustellen, ob ein 502-Fehler durch eine Socket-Fehlkonfiguration verursacht wurde, bestätigen Sie, dass PHP-FPM und NGINX so konfiguriert sind, dass sie denselben Socket verwenden. PHP-FPM verwendet eine separate Konfigurationsdatei für jeden Worker-Prozesspool; Diese Dateien befinden sich unter /etc/php/7.2/fpm/pool.d/. Der Socket jedes Pools ist in einer listen
Direktive in der Konfigurationsdatei des Pools definiert. Zum Beispiel konfiguriert die listen
Direktive unten einen Pool mit dem Namen mypool
, um einen Unix-Socket zu verwenden, der sich unter /run/php/mypool .socke:
mypool.conf
listen = /run/php/mypool.sock
Wenn NGINX nicht auf den Socket für einen bestimmten Pool zugreifen kann, können Sie feststellen, welcher Worker-Pool an dem Problem beteiligt ist, indem Sie überprüfen, welcher Socket im NGINX-Fehlerprotokolleintrag benannt ist. Wenn PHP-FPM beispielsweise den mypool
Worker-Pool nicht gestartet hätte, würde NGINX eine 502 zurückgeben und sein Fehlerprotokolleintrag würde Folgendes enthalten:
Fehler.log
connect() to unix:/run/php/mypool.sock failed (2: No such file or directory)
Überprüfen Sie Ihren nginx.conf-Datei, um sicherzustellen, dass der relevante location
-Block denselben Socket angibt. Das folgende Beispiel enthält eine include
Direktive, die einige allgemeine Konfigurationsinformationen für PHP-FPM lädt, und eine fastcgi_pass
Direktive, die denselben Unix-Socket angibt, der im mypool benannt ist.conf-Datei, oben.
nginx.conf
location / { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/mypool.sock;}
Unix-Sockets unterliegen Unix-Dateisystemberechtigungen. Die Konfigurationsdatei des PHP-FPM-Pools gibt den Modus und den Besitz des Sockets an, wie hier gezeigt:
www.conf
listen.owner = www-datalisten.group = www-datalisten.mode = 0660
Stellen Sie sicher, dass diese Berechtigungen dem Benutzer und der Gruppe, die NGINX ausführen, den Zugriff auf den Socket ermöglichen. Wenn die Berechtigungen für den Socket falsch sind, protokolliert NGINX einen 502-Fehler in seinem Zugriffsprotokoll und eine Meldung wie die unten gezeigte in seinem Fehlerprotokoll:
error .log
2020/02/20 17:12:03 3059#3059: *4 connect() to unix:/run/php/mypool.sock failed (13: Permission denied) while connecting to upstream, client: 127.0.0.1, server: localhost, request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/run/php/mypool.sock:", host: "localhost"
Beachten Sie, dass die Standardwerte von listen.owner
und listen.group
mit dem Standardbesitzer und der Gruppe übereinstimmen, die NGINX ausführen, und listen.mode
standardmäßig 0660. Mit diesen Standardeinstellungen sollte NGINX auf den Socket zugreifen können.
Wenn PHP-FPM einen TCP-Socket überwacht, hat die listen
Direktive der Poolkonfiguration einen Wert in der Form address:port
, wie unten gezeigt:
www.conf
listen = 127.0.0.1:9000
Genau wie bei einem Unix-Socket können Sie 502-Fehler verhindern, indem Sie bestätigen, dass die Position dieses Sockets mit der in der NGINX-Konfiguration angegebenen übereinstimmt.
PHP-FPM läuft ab
Wenn die Antwort Ihrer Anwendung zu lange dauert, tritt bei Ihren Benutzern ein Timeout-Fehler auf. Wenn das Timeout von PHP-FPM — das in der Direktive request_terminate_timeout
der Poolkonfiguration festgelegt ist (und standardmäßig 20 Sekunden beträgt) – kleiner ist als das Timeout von NGINX (standardmäßig 60 Sekunden), antwortet NGINX mit einem 502-Fehler. Das unten gezeigte NGINX-Fehlerprotokoll zeigt an, dass der vorgelagerte Prozess — PHP-FPM — die Verbindung geschlossen hat, bevor eine gültige Antwort gesendet wurde. Mit anderen Worten, dies ist das Fehlerprotokoll, das wir sehen, wenn PHP-FPM eine Zeitüberschreitung aufweist:
error .log
2020/02/20 17:17:12 3059#3059: *29 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 127.0.0.1, server: localhost, request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/run/php/mypool.sock:", host: "localhost"
In diesem Fall das PHP-FPM-Protokoll (das sich standardmäßig unter /var/log/php7.2-fpm befindet.log) zeigt eine korrelierte Nachricht, die weitere Informationen liefert:
php7.2-fpm.log
WARNING: child 2120, script '/var/www/html/index.php' (request: "GET /index.php") execution timed out (25.755070 sec), terminating
Sie können die Timeout-Einstellung von PHP-FPM erhöhen, indem Sie die Konfigurationsdatei des Pools bearbeiten. Das Standard-NGINX-Timeout beträgt 60 Sekunden; wenn Sie Ihr PHP-FPM-Timeout über 60 Sekunden erhöht haben, gibt NGINX einen 504 Gateway-Timeout-Fehler zurück, wenn Ihre PHP-Anwendung nicht rechtzeitig geantwortet hat. Sie können dies verhindern, indem Sie auch Ihr NGINX-Timeout erhöhen. Im folgenden Beispiel haben wir den Timeout-Wert auf 90 Sekunden erhöht, indem wir den fastcgi_read_timeout
-Eintrag zum http
-Block von /etc/nginx/nginx hinzugefügt haben.conf:
nginx.conf
http { ... fastcgi_buffers 8 16k; fastcgi_buffer_size 32k; fastcgi_connect_timeout 90; fastcgi_send_timeout 90; fastcgi_read_timeout 90;}
Laden Sie Ihre NGINX-Konfiguration neu, um diese Änderung zu übernehmen:
nginx -s reload
Um festzustellen, warum PHP-FPM abgelaufen ist, können Sie als nächstes Protokolle und APM-Daten (Application Performance Monitoring) sammeln, die Ursachen für die Latenz innerhalb und außerhalb Ihrer Anwendung aufdecken können.
Sammeln und Analysieren Sie Ihre Protokolle
Um Anwendungsfehler zu beheben, können Sie Ihre Protokolle sammeln und an einen Protokollverwaltungsdienst senden. Zusätzlich zu den oben untersuchten NGINX-Protokollen kann PHP Fehler und andere Ereignisse protokollieren, die für Sie wertvoll sein könnten. Weitere Informationen finden Sie in unserem PHP Logging Guide.
Wenn Sie Ihre PHP- und NGINX-Protokolle in einen Protokollverwaltungsdienst einbinden, kombiniert mit Protokollen von relevanten Technologien wie Caching-Servern und Datenbanken, können Sie Protokolle aus Ihrem gesamten Web-Stack auf einer einzigen Plattform analysieren.
Sammeln Sie APM-Daten von Ihrem Webstack
APM kann Ihnen helfen, Engpässe zu identifizieren und Probleme wie 502-Fehler zu beheben, die sich auf die Leistung Ihrer App auswirken. Der folgende Screenshot zeigt die in Datadog visualisierten APM-Daten von NGINX. Diese Ansicht fasst das Anforderungsvolumen, die Fehlerraten und die Latenz für einen NGINX-basierten Dienst zusammen und hilft Ihnen bei der Untersuchung von Leistungsproblemen wie 502-Fehlern.
200 OK
Je schneller Sie die 502-Fehler Ihrer Anwendung diagnostizieren und beheben können, desto besser. Mit Datadog können Sie Metriken, Traces, Protokolle und Netzwerkleistungsdaten aus Ihrer gesamten Infrastruktur analysieren. Wenn Sie bereits Datadog-Kunde sind, können Sie mit der Überwachung von NGINX, PHP-FPM und mehr als 400 anderen Technologien beginnen. Wenn Sie noch kein Datadog-Konto haben, melden Sie sich für eine 14-tägige kostenlose Testversion an und legen Sie in wenigen Minuten los.
Leave a Reply