wake-up-neo.net

NginX gibt trotz Konfig eine HTTP 499-Fehlermeldung nach 60 Sekunden aus. (PHP und AWS)

Ende letzter Woche habe ich ein Problem in einer meiner mittleren AWS-Instanzen festgestellt, bei dem Nginx immer eine HTTP 499-Antwort zurückgibt, wenn eine Anforderung mehr als 60 Sekunden dauert. Die angeforderte Seite ist ein PHP -Skript

Ich habe mehrere Tage versucht, Antworten zu finden und habe alles versucht, was ich im Internet finden kann, einschließlich einiger Einträge hier bei Stack Overflow. Nichts funktioniert.

Ich habe versucht, die Einstellungen für PHP, PHP-FPM und Nginx zu ändern. Sie können eine Frage sehen, die ich am Freitag in den NginX-Foren angesprochen habe ( http://forum.nginx.org/read.php?9,237692 ), obwohl dies keine Antwort erhalten hat, also hoffe ich, dass ich es bin Ich kann hier eine Antwort finden, bevor ich gezwungen bin, nach Apache zurückzukehren, von dem ich weiß, dass er gerade funktioniert.

Dieses ist nicht dasselbe Problem wie die in anderen Einträgen gemeldeten HTTP 500-Fehler.

Ich konnte das Problem mit einer frischen Micro-AWS-Instanz von NginX mit PHP 5.4.11 replizieren.

Um jedem zu helfen, der das Problem in Aktion sehen möchte, werde ich Sie durch das Setup führen, das ich für den neuesten Micro-Testserver durchführte.

Sie müssen eine neue AWS Micro-Instanz (also kostenlos) mit AMI ami-c1aaabb5 starten

Dieser Pastebin-Eintrag ist vollständig eingerichtet, um meine Testumgebung zu spiegeln. Sie müssen lediglich example.com in der NginX-Konfiguration am Ende ändern

http://Pastebin.com/WQX4AqEU

Nach der Einrichtung müssen Sie lediglich die Beispieldatei PHP erstellen, mit der ich teste

<?php
sleep(70);
die( 'Hello World' );
?>

Speichern Sie das in der Webroot und testen Sie dann. Wenn Sie das Skript mit php oder php-cgi von der Befehlszeile aus ausführen, funktioniert es. Wenn Sie über eine Webseite auf das Skript zugreifen und das Zugriffsprotokoll /var/log/nginx/example.access.log abschließen, werden Sie nach 60 Sekunden feststellen, dass Sie die Antwort HTTP 1.1 499 erhalten.

Nun, da Sie die Zeitüberschreitung sehen können, werde ich einige der Konfigurationsänderungen durchgehen, die ich an PHP und NginX vorgenommen habe, um zu versuchen, dies zu umgehen. Für PHP erstelle ich mehrere Konfigurationsdateien, damit sie leicht deaktiviert werden können

PHP FPM-Konfig aktualisieren, um externe Konfigurationsdateien einzuschließen

Sudo echo '
include=/usr/local/php/php-fpm.d/*.conf
' >> /usr/local/php/etc/php-fpm.conf

Erstellen Sie eine neue PHP-FPM-Konfiguration, um das Anforderungszeitlimit zu überschreiben.

Sudo echo '[www]
request_terminate_timeout = 120s
request_slowlog_timeout = 60s
slowlog = /var/log/php-fpm-slow.log ' >
/usr/local/php/php-fpm.d/timeouts.conf

Ändern Sie einige der globalen Einstellungen, um sicherzustellen, dass das Notfall-Neustartintervall 2 Minuten beträgt.

# Create a global tweaks
Sudo echo '[global]
error_log = /var/log/php-fpm.log
emergency_restart_threshold = 10
emergency_restart_interval = 2m
process_control_timeout = 10s
' > /usr/local/php/php-fpm.d/global-tweaks.conf

Als Nächstes werden wir einige der PHP.INI-Einstellungen ändern, wobei wiederum separate Dateien verwendet werden

# Log PHP Errors
Sudo echo '[PHP]
log_errors = on
error_log = /var/log/php.log
' > /usr/local/php/conf.d/errors.ini

Sudo echo '[PHP]
post_max_size=32M
upload_max_filesize=32M
max_execution_time = 360
default_socket_timeout = 360
mysql.connect_timeout = 360
max_input_time = 360
' > /usr/local/php/conf.d/filesize.ini

Wie Sie sehen, erhöht dies das Socket-Timeout auf 3 Minuten und hilft, Fehler zu protokollieren.

Zum Schluss bearbeite ich einige der NginX-Einstellungen, um das Timeout auf dieser Seite zu erhöhen

Zuerst bearbeite ich die Datei /etc/nginx/nginx.conf und füge diese der http-Direktive .__ hinzu. fastcgi_read_timeout 300;

Als Nächstes bearbeite ich die zuvor erstellte Datei /etc/nginx/sites-enabled/example (siehe den Eintrag Pastebin) und füge die folgenden Einstellungen in die Direktive server ein

client_max_body_size    200;
client_header_timeout   360;
client_body_timeout     360;
fastcgi_read_timeout    360;
keepalive_timeout       360;
proxy_ignore_client_abort on;
send_timeout            360;
lingering_timeout       360;

Schließlich füge ich Folgendes in den Abschnitt location ~ .php $ des Serververzeichnisses ein

fastcgi_read_timeout 360;
fastcgi_send_timeout 360;
fastcgi_connect_timeout 1200;

Bevor Sie das Skript erneut versuchen, starten Sie sowohl nginx als auch php-fpm, um sicherzustellen, dass die neuen Einstellungen übernommen wurden. Ich versuche dann, auf die Seite zuzugreifen, und erhalte immer noch den Eintrag HTTP/1.1 499 in der NginX-Datei example.error.log.

Also, wohin gehe ich falsch? Dies funktioniert nur bei Apache, wenn ich die maximale Ausführungszeit von PHP auf 2 Minuten festlege.

Ich kann sehen, dass die PHP -Einstellungen durch Ausführen von phpinfo () von einer über das Web zugänglichen Seite übernommen wurden. Ich verstehe es einfach nicht, ich denke tatsächlich, dass zu viel erhöht wurde, da es nur die max_execution_time von PHP benötigen sollte, default_socket_timeout sowie NginXs fastcgi_read_timeout nur am server-> location geändert wurde Richtlinie.

Update 1

Nachdem ich einige weitere Tests durchgeführt habe, um zu zeigen, dass das Problem nicht darin besteht, dass der Client stirbt, habe ich die Testdatei geändert

<?php
file_put_contents('/www/log.log', 'My first data');
sleep(70);
file_put_contents('/www/log.log','The sleep has passed');
die('Hello World after sleep');
?>

Wenn ich das Skript von einer Webseite aus laufe, kann ich sehen, dass der Inhalt der Datei auf die erste Zeichenfolge gesetzt wird. 60 Sekunden später erscheint der Fehler im NginX-Protokoll. 10 Sekunden später ändert sich der Inhalt der Datei in die 2. Zeichenfolge. Dies zeigt, dass PHP den Vorgang abschließt.

Update 2

Durch die Einstellung von fastcgi_ignore_client_abort on; wird die Antwort von einem HTTP 499 zu einem HTTP 200 geändert, obwohl nichts an den Endclient zurückgegeben wird.

Update 3

Nach der Installation von Apache und PHP (5.3.10) auf der Box (mit apt) und anschließender Erhöhung der Ausführungszeit scheint das Problem auch auf Apache zu bestehen. Die Symptome sind jetzt die gleichen wie bei NginX, eine HTTP200-Antwort, die tatsächliche Client-Verbindung läuft jedoch vorzeitig ab.

Ich habe auch in den NginX-Protokollen bemerkt, dass ich, wenn ich Firefox teste, eine doppelte Anforderung stellt (wie dieses PHP - Skript zweimal ausgeführt wird, wenn es länger als 60 Sekunden ist ). Dies scheint jedoch der Client zu sein, der anfordert, dass das Skript fehlschlägt

51
TFAtTheMoon

Die Ursache des Problems sind die elastischen Lastverteiler in AWS. Standardmäßig tritt nach 60 Sekunden Inaktivität ein Timeout auf, was das Problem verursacht hat.

Also nicht NginX, PHP-FPM oder PHP, sondern der Load Balancer.

Um dies zu beheben, wechseln Sie einfach in die ELB-Registerkarte "Beschreibung", scrollen Sie nach unten und klicken Sie auf den Link "(Bearbeiten)" neben dem Wert, der "Idle Timeout: 60 Sekunden" angibt.

59
TFAtTheMoon

Ich dachte, ich würde meine zwei Cents verlassen. Zunächst hängt das Problem nicht mit php zusammen (es könnte sich auch um ein php-Problem handeln, php überrascht mich immer wieder: P). Das ist sicher. Dies ist in erster Linie auf einen Server zurückzuführen, der auf sich selbst verweist, insbesondere auf den Namen von Hostnamen/Aliasnamen. In Ihrem Fall könnte es sein, dass der Lastverteiler Nginx anfordert und Nginx den Lastverteiler zurückruft, und dies geschieht weiterhin. 

Ich habe ein ähnliches Problem mit Nginx als Load Balancer und Apache als Webserver/Proxy erlebt

1
Waheed

Ich bin mir nicht sicher, ob jemand anderes mit diesem Problem konfrontiert ist, aber für mich geschah es, nachdem ich einen / am Ende meiner Instanz url. gesetzt hatte. Dieser gab 499 error und erst nachdem ich den / entfernt hatte, gab es 200 und alles lief gut.

0
Souvik Ray

Eigentlich war ich auf einem Server mit dem gleichen Problem konfrontiert und habe herausgefunden, dass ich den Nginx-Server nach den Konfigurationsänderungen von Nginx nicht neu gestartet habe. Mit jedem Treffer der Nginx-URL erhielt ich eine 499-http-Antwort. Nach dem Neustart von nginx funktionierte es ordnungsgemäß mit den Antworten von http 200.

0
Rajeev kumar

Sie müssen an welchem ​​Ort das Problem live finden. Ich weiß es nicht genau, aber versuchen wir es einfach zu finden.

Wir haben hier 3 Elemente: nginx, php-fpm, php. Wie gesagt, die gleichen PHP-Einstellungen unter Apache sind in Ordnung. Ist es nicht gleich Setup? Haben Sie Apache anstelle von Nginx auf demselben OS/Host/etc ausprobiert?

Wenn wir sehen, dass php nicht verdächtig ist, dann haben wir zwei Verdächtige: nginx & php-fpm.

Um nginx auszuschließen: Versuchen Sie, dasselbe "System" in Ruby einzurichten. Siehe https://github.com/garex/puppet-module-nginx , um die einfachsten Ruby-Einstellungen zu installieren. Oder benutze Google (vielleicht wird es sogar noch besser).

Mein Hauptverdächtiger hier ist PHP-Fpm.

Versuchen Sie, mit diesen Einstellungen zu spielen:

  • php-fpm`s request_terminate_timeout
  • nginx`s fastcgi_ignore_client_abort
0
gaRex