Bei einem unserer Webprojekte ist aufgrund der Zunahme neuer Städte ein Anstieg des Datenverkehrs und des DB-Drucks zu verzeichnen. Als Geschäftsanbieter der Schnittstelle haben wir in letzter Zeit eine große Anzahl von „502“-Anfragen aus nachgelagertem Feedback erhalten. 502, Bad Gateway, wird normalerweise durch einen Upstream-Fehler (in diesem Fall PHP) verursacht. Bei PHP ist die häufigste Ursache für 502, dass die Skriptausführung die eingestellte Timeout-Zeit überschreitet oder die Timeout-Einstellung zu groß ist, was dazu führt, dass der PHP-Prozess lange Zeit nicht freigegeben werden kann und kein inaktiver Worker-Prozess den Client empfangen kann. Unser Projekt wird durch eine zu kurze PHP-Ausführungszeit verursacht. In diesem Fall können wir die PHP-Ausführungszeit entsprechend erhöhen, um sicherzustellen, dass 502 zuerst gelöscht wird. Schließlich nimmt die Optimierung mehr Zeit in Anspruch. Es gibt zwei Optionen zur Steuerung 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, müssen Sie nur die php-fpm-Konfiguration ändern. Als Nächstes werde ich im Detail analysieren, warum die Ausführung des PHP-Skripts die festgelegte Zeit überschreitet und dazu führt, dass nginx 502 zurückgibt. Lassen Sie uns zunächst die Situation beschreiben, um das Problem zu reproduzieren: Nginx und PHP starten jeweils nur einen Worker, um die Nachverfolgung zu erleichtern. Das request_terminate_timeout von php-fpm ist auf 3 S eingestellt. Testskript test.php Schlaf (20); echo "ok"; Geh! Geh! Geh: Besuchen Sie www.v.com/test.php im Browser und nach 3 Sek. lautet das Ergebnis ... 404? ? ? Was? ? ? Der Start ist nicht gut, schauen wir uns die Nginx-Konfigurationsdatei an Diese Standortkonfiguration dient dazu, bei Auftreten eines 5xx-Fehlers zu einer besser aussehenden Schnittstelle zu springen, aber ich habe die Datei 50x.html nicht in /usr/share/nginx/html. Ich habe also einen 404-Fehler erhalten. Beeinträchtigt dies nicht die Genauigkeit meines Urteils? Kommentieren Sie es einfach aus! Besuchen Sie es erneut, warten Sie 3 Sekunden und schließlich wird die „normale“ Benutzeroberfläche angezeigt. Nachdem die Umgebung nun bereit ist, folgen wir der Routine und gehen die Fehlerbehebungsroutine für Webprobleme durch. Werfen wir zunächst einen Blick auf das Fehlerprotokoll: nginx: Die Fehlermeldungen lauten alle „recv() failed (104: Verbindung vom Peer zurückgesetzt. Der Empfang ist fehlgeschlagen und die Verbindung wurde zurückgesetzt. Warum wurde die Verbindung zurückgesetzt? Gibt es eine Meinungsverschiedenheit? Werfen wir einen Blick auf das Fehlerprotokoll von php-fpm: (Beachten Sie, dass die Option php_admin_value[error_log] in php-fpm das PHP-Fehlerprotokoll angibt, das das in php.ini überschreibt. Allerdings betrachten wir hier keine PHP-Fehler, sondern PHP-fpm-Fehler. Das PHP-fpm-Fehlerprotokoll wird durch die Option error_log in php-fpm.conf angegeben.) Jede Anfrage generiert 2 WARNUNGEN und 1 HINWEIS: WARNUNG: Bei der Skriptausführung ist eine Zeitüberschreitung aufgetreten und das Skript wurde beendet. WARNUNG: Der untergeordnete Prozess hat ein SIGTERM-Signal erhalten und wurde beendet. HINWEIS: Ein neuer untergeordneter Prozess wurde gestartet (weil ich pm.min_spare_servers = 1 gesetzt habe) Es scheint, dass bei einer Zeitüberschreitung der Ausführung des PHP-Arbeitsprozesses nicht nur die Skriptausführung beendet wird, sondern auch der Arbeitsprozess beendet wird. Es scheint, dass die Nginx-Fehlerverbindung zurückgesetzt wurde, weil der PHP-Arbeitsprozess beendet wurde (bei einer TCP-Verbindung wird RST an die andere Partei gesendet, wenn die Verbindung getrennt wird). Aus dem Protokoll können wir erkennen, dass die Ausführung des PHP-Skripts abgelaufen ist und der untergeordnete Worker-Prozess beendet wurde, was dazu führte, dass nginx den Fehler „Verbindung vom Peer zurückgesetzt“ meldete. Als Nächstes verwenden wir strace, um die Situation von PHP und nginx zu untersuchen: php: 1. Akzeptieren Sie eine Nginx-Verbindungsanforderung (Socket, Bind und Listen werden alle im Master abgeschlossen). Sie können sehen, dass der Port von Nginx 47039 ist. Lesen Sie Daten von FD0, also von der Standardeingabe. Dies wird durch das Fast-CGI-Protokoll festgelegt. Der verbundene Deskriptor nach dem Akzeptieren ist 3. 2. Lesen Sie die von nginx von FD3 übergebenen Daten im Fastcgi-Protokollformat und empfangen Sie 856 Bytes. Warum 5 mal lesen? Denn das Datenpaket des FastCGI-Protokolls ist 8-Byte-ausgerichtet und besteht aus einem Header und einem Body. Und sie senden zuerst ein Anforderungsdatenpaket, das eine Anforderungs-ID, Version, Typ und andere Informationen enthält (Header und Textkörper umfassen jeweils 8 Bytes). Dann senden sie ein Parameterdatenpaket, um Parameter und Umgebungsvariablen zu übergeben (der Header ist 8 Bytes lang, der Textkörper ist länger) und senden schließlich ein Parameterdatenpaket ohne Textkörper, sondern nur mit einem Header, das das Ende der Parameterübermittlung anzeigt (der Header ist 8 Bytes lang). Die ersten drei Lesevorgänge dienen also zum Lesen des Headers und des Hauptteils des Anforderungspakets sowie des Headers des Parameterpakets. Der vierte Lesevorgang dient zum Lesen der eigentlichen Daten und der letzte Lesevorgang zum Lesen des Headers des letzten Parameterpakets. Daher sollten die von nginx übertragenen Daten 8 + 8 + 8 + 856 + 8 = 896 Bytes betragen (was den unten aufgeführten Übertragungsbytes von nginx entspricht). Beachten Sie, dass bei Verwendung der Post-Methode auch das Stdin-Datenpaket gesendet wird. 3. Stellen Sie die Ruhezeit auf 20 Sekunden ein, was im PHP-Programm sleep(20) ist. Da der Prozess beendet wird, gibt es nichts mehr. Das Strace-Programm wird ebenfalls beendet. nginx: 1. Akzeptieren Sie die Anfrage an den Browser. Sie können sehen, dass der Port auf der Browserseite 56434, die IP 192.168.1.105 und der FD der hergestellten Verbindung 3 ist. 2. Daten vom FD3 empfangen, 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 zum Port 9000 des lokalen Computers besteht. Hier verwenden nginx und php-fpm die IP-Socket-Verbindungsmethode. Wenn nginx und php-fpm auf demselben Computer bereitgestellt werden, können Sie einen Unix-Domain-Socket in Betracht ziehen. 5. Schreiben Sie Daten im Fast-CGI-Protokollformat in FD21. Wir sehen, dass die geschriebene Länge 896 beträgt, was der oben von PHP empfangenen Länge entspricht. 6. Die Funktion recvfrom gibt ECONNRESET (Verbindungsreset durch Peer) von FD21 zurück. 7. Schreiben Sie Fehlerinformationen in FD9. Daraus lässt sich schließen, dass FD9 der Dateideskriptor des Nginx-Fehlerprotokolls ist. 8. Schließen Sie die Verbindung mit FD21. 9. Schreiben Sie 502 Bad Gateway in FD3. Dies sind die Informationen, die an den Browser zurückgegeben werden. 10. Schreiben Sie ein Zugriffsprotokoll in FD8. Daraus lässt sich schließen, dass FD8 der Dateideskriptor des Nginx-Zugriffsprotokolls ist. Lassen Sie uns die Schlussfolgerung des Nginx-Zugriffsprotokolls und des Fehlerprotokolls überprüfen. Es ist ersichtlich, dass es sich tatsächlich um FD8 und FD9 handelt und dass es sich im Schreibmodus befindet. Schauen wir uns dann die Übertragung des gesamten Netzwerkpakets in diesem Prozess an: Es ist bequemer, Pakete über tcpdump zu erfassen und das Artefakt zum Anzeigen dieser zu verwenden. Da ich nur die Kommunikation zwischen nginx und php sehen möchte und weiß, dass der Port von nginx 47039 ist, kann ich die entsprechenden Pakete über tcp.srcport==47039 herausfiltern. Sie können den Dateninteraktionsprozess zwischen nginx und php-fpm sehen: 47039->9000 stellt einen Drei-Wege-Handshake her, sendet dann Daten an 9000, 9000 antwortet mit ACK und 9000 antwortet nach 3 S mit RST. Nichts Schlimmes. Beachten: SYN und FIN belegen jeweils eine Sequenznummer ACK und RST belegen nicht die Sequenznummer (die Reqnum und Acknowlum der Pakete 28 und 29 sind gleich) Die Sequenznummer ist 1 für jedes Byte (Paket 29 sendet 896 Bytes, und die Sequenz von Paket 29 ist 4219146879, und die Bestätigung von Paket 30 ist 4219147775, was genau 896 Bytes Unterschied ist). RST erfordert keine Antwort. Das Obige ist der vollständige Inhalt dieses Artikels. Ich hoffe, er wird für jedermanns Studium hilfreich sein. Ich hoffe auch, dass jeder 123WORDPRESS.COM unterstützen wird. Das könnte Sie auch interessieren:
|
<<: So finden Sie die my.ini-Konfigurationsdatei in MySQL 5.6 unter Windows
>>: Zusammenfassung des MySQL-Installationsdiagramms
Das Befehlsformat für die MySQL-Anmeldung ist: my...
Verzögertes Laden (Lazy Loading) und Vorladen sin...
1 Wirkung Demo-Adresse: https://www.albertyy.com/...
Bei der Verwendung einer MySQL-Datenbank treten h...
Inhaltsverzeichnis Was ist ein Skelettbildschirm?...
1. Erster Download von der offiziellen Website vo...
Dieser Artikel enthält das grafische Tutorial zur...
Wie fügt man CSS in HTML ein? Es gibt drei Möglic...
Code kopieren Der Code lautet wie folgt: .sugLaye...
Sie können das Desktopsystem von der offiziellen ...
Hintergrund Mit der Entwicklung des Geschäfts exp...
Szenario 1. Pflegen Sie ein Bürgersystem mit eine...
Inhaltsverzeichnis 1. Prototyp-Beziehung 2. Proto...
brauchen: Normalerweise wollen Websites verhinder...
In diesem Artikelbeispiel wird der spezifische Co...