Bei einem unserer Webprojekte sind durch die Zunahme neuer Städte die Besuchszahlen gestiegen und der Druck auf die DB gestiegen. Als Wirtschaftspartner, der Schnittstellen bereitstellt, kam es in letzter Zeit zu einer Vielzahl von „502“-Anfragen durch nachgelagertes Feedback gemeldet.
502, schlechtes Gateway, ist normalerweise ein Fehler im Upstream (hier PHP). Bei PHP liegt die häufigste Ursache für 502 darin, dass die Skriptausführung die Zeitüberschreitungszeit überschreitet oder die Zeitüberschreitungseinstellung zu groß ist, was dazu führt, dass der PHP-Prozess abstürzt nicht für längere Zeit freigegeben werden. Es gibt keine Leerlaufprozesse, um Kunden abzuholen.
Unser Projekt wird dadurch verursacht, dass die PHP-Ausführungszeit zu kurz eingestellt ist. In diesem Fall können Sie zunächst die PHP-Ausführungszeit entsprechend erhöhen und sicherstellen, dass die Optimierung zunächst mehr Zeit in Anspruch nimmt.
Es gibt zwei Optionen zum Steuern der PHP-Ausführungszeit: max_execution_time in php.ini und request_terminate_timeout in php-fpm. request_terminate_timeout kann max_execution_time überschreiben. Wenn Sie also die globale php.ini nicht ändern möchten, ändern Sie einfach die Konfiguration von php -fpm. Das ist es.
Als nächstes werde ich im Detail analysieren, warum Nginx 502 zurückgibt, wenn die Ausführung des PHP-Skripts die festgelegte Zeit überschreitet.
Lassen Sie uns zunächst die Situation festlegen und das Problem reproduzieren:
Nginx und PHP starten jeweils nur einen Worker, um die Nachverfolgung zu erleichtern.
php-fpms request_terminate_timeout ist auf 3s eingestellt.
Testskript test.php
sleep(20); echo 'ok';
go go go:
Besuchen Sie www.v.com/test.php im Browser, 3 Sekunden später... erscheint 404 wie erwartet? ? ? Was? ? ?
Es ist ein schlechter Anfang. Schauen Sie sich die Nginx-Konfigurationsdatei an.
Diese Speicherortkonfiguration dient dazu, zu einer schöneren Schnittstelle zu springen, wenn ein 5xx-Fehler auftritt, aber ich habe sie in /usr/share/nginx gefunden /html Darunter befindet sich keine 50x.html-Datei. Also habe ich einen 404 bekommen. Beeinträchtigt dies nicht die Genauigkeit meiner Beurteilung des Problems? Kommentiere es einfach aus! Besuchen Sie es erneut, warten Sie 3 Sekunden und schließlich wird die „normale“ Benutzeroberfläche angezeigt.
Da die Umgebung nun bereit ist, folgen wir der Routine zur Fehlerbehebung für Webprobleme:
nginx:
Die gemeldeten Fehler sind recv. ) fehlgeschlagen (104: Verbindung vom Peer zurückgesetzt.
recv fehlgeschlagen, die Verbindung wurde zurückgesetzt. Warum wurde die Verbindung zurückgesetzt?
Wir sehen uns das Fehlerprotokoll von php-fpm an:
Die Option php_admin_value[error_log] gibt die an Fehlerprotokoll von PHP, das den Fehler in php.ini überschreibt. Dies ist jedoch nicht der Fehler von php, sondern der Fehler von php-fpm Option ist angegeben.)
Jede Anfrage generiert 2 Warnungen und 1 Hinweis:
Warnung: Die Skriptausführung ist abgelaufen und wurde beendet.
Warnung: Der untergeordnete Prozess hat das Sigterm-Signal empfangen und beendet ein neuer untergeordneter Prozess (weil ich pm.min_spare_servers = 1 gesetzt habe)
Es scheint, dass bei einer Zeitüberschreitung bei der Ausführung des PHP-Worker-Prozesses nicht nur die Skriptausführung beendet wird, sondern auch der Worker-Prozess beendet wird. Der Fehler Die Verbindung wurde zurückgesetzt, weil der PHP-Worker-Prozess beendet wurde (wenn eine Partei in der TCP-Verbindung getrennt wird, sendet sie zuerst an die andere Partei)
Aus dem Protokoll ist ersichtlich, dass die Ausführung des PHP-Skripts abgelaufen ist und der Worker-Sub- Der Prozess wurde beendet, was dazu führte, dass Nginx einen Fehler beim Zurücksetzen der Verbindung durch den Peer meldete. Nachfolgend verwenden wir Strace, um die Situation von PHP und Nginx anzuzeigen:
php:
1. Akzeptieren Sie eine Nginx-Verbindungsanfrage (Socket, binden und abhören). sind alle im Master abgeschlossen), Sie können sehen, dass der Port zu nginx 47039 ist. Das Lesen von Daten von fd0 erfolgt über die Standardeingabe. Dies wird durch das Fast-CGI-Protokoll angegeben. Nginx-Übertragung von fd3 lesen. Die eingehenden Daten liegen im Fastcgi-Protokollformat vor und werden 856 Bytes empfangen.
Weil das Fastcgi-Protokoll-Datenpaket 8-Byte-ausgerichtet ist und aus einem Paket-Header und einem Paket-Körper besteht. Und es wird zuerst ein Anforderungspaket gesendet, das einige Anforderungs-ID, Version, Typ und andere Informationen enthält (der Header und der Text belegen jeweils 8 Bytes), und dann wird ein Parameterpaket gesendet, um die Get-Parameter und Umgebungsvariablen zu übergeben (der Header ist 8). Bytes), der Paketkörper wird länger), und schließlich wird ein Parameterdatenpaket ohne Paketkörper und nur ein Paketkopf gesendet, was das Ende des Parameterversands anzeigt (8 Byte Paketkopf). Die ersten drei Lesevorgänge werden also zum Lesen des Headers und des Hauptteils des Anforderungspakets sowie des Headers des Parameterpakets verwendet. Beim vierten Lesevorgang werden die tatsächlichen Daten gelesen, und beim letzten Lesevorgang wird der Header des letzten gelesen params-Paket. Daher sollten die von Nginx übertragenen Daten 8 + 8 + 8 + 856 + 8 = 896 Bytes groß sein (was den unten aufgeführten Übertragungsbytes von Nginx entsprechen kann). Beachten Sie, dass im Post-Modus auch Standard-Datenpakete gesendet werden.
3. Stellen Sie den Ruhezustand auf 20 Sekunden ein, was im PHP-Programm der Ruhezustand (20) ist. Da der Prozess danach beendet ist, wird es keinen weiteren geben. Das Strace-Programm wurde ebenfalls beendet.
nginx:
1.Akzeptieren Sie die Anfrage an den Browser. Sie können sehen, dass der Port im Browser 56434 ist, die IP 192.168.1.105 ist und die fd der hergestellten Verbindung 3 ist.
2. Empfangen Sie Daten von fd3, http-Protokoll.
3. Erstellen Sie einen Socket, fd21, um eine Verbindung mit PHP herzustellen.
4. Stellen Sie eine Verbindung zu fd21 her. Sie können sehen, dass die Verbindung der 9000-Port des lokalen Computers ist. Hier verwenden Nginx und PHP-FPM die IP-Socket-Verbindungsmethode kann in Betracht gezogen werden.
5. Schreiben Sie Daten in das Fast-CGI-Protokollformat fd21. Wir sehen, dass die geschriebene Länge 896 beträgt, was der oben von PHP empfangenen Länge entspricht.
6. Die recvfrom-Funktion gibt econnreset (Verbindung zurückgesetzt durch Peer) von fd21 zurück.
7 Daraus kann geschlossen werden, dass fd9 der Dateideskriptor des Nginx-Fehlerprotokolls ist.
8. Schließen Sie die Verbindung mit fd21.
9. Schreiben Sie 502 Bad Gateway in fd3, das sind die an den Browser zurückgegebenen Informationen.
10. Schreiben Sie ein Zugriffsprotokoll auf fd8. Daraus kann geschlossen werden, dass fd8 der Dateideskriptor des Nginx-Zugriffsprotokolls ist.
Lassen Sie uns die Schlussfolgerung von Nginx-Zugriffsprotokollen und Fehlerprotokollen überprüfen. Sie können sehen, dass es sich tatsächlich um fd8, fd9 und im Schreibmodus handelt.
Dann können wir uns genauso gut die Übertragung des gesamten Netzwerkpakets in diesem Prozess ansehen:
Erfassen Sie das Paket über tcpdump. Es ist bequemer, ein Artefakt zum Anzeigen zu verwenden.
Da ich nur die Kommunikation zwischen Nginx und PHP sehen möchte und aus dem oben Gesagten weiß, dass der Port von Nginx 47039 ist, kann ich das entsprechende Paket über tcp.srcport==47039 herausfiltern.
Sie können den Prozess der Dateninteraktion zwischen Nginx und PHP-FPM sehen: 47039->9000 stellt einen Drei-Wege-Handshake her und sendet dann Daten an 9000, 9000 antwortet mit Bestätigung und 9000 antwortet mit Rst nach 3 Sekunden . Nichts falsch.
Hinweis:
syn, fin belegen jeweils eine Sequenznummer
ack, rst belegen keine Sequenznummer (Reqnum und Acknum der beiden Pakete 28 und 29 sind gleich)
Die Sequenznummer wird um 1 addiert Für jedes Byte (29 Pakete senden 896 Bytes, während die Sequenz von 29 Paketen 4219146879 ist und die Bestätigung von 30 Paketen 4219147775 ist, was genau einer Differenz von 896 entspricht)
rst erfordert keine Antwort.
Das obige ist der detaillierte Inhalt vonSo lösen Sie den HTTP-Statuscode 502 des Nginx+php-fpm-Dienstes. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!