web-dev-qa-db-fra.com

NginX émet une erreur HTTP 499 après 60 secondes malgré la configuration. (PHP et AWS)

À la fin de la semaine dernière, j'ai remarqué un problème sur l'une de mes instances AWS moyennes où Nginx renvoie toujours une réponse HTTP 499 si une demande prend plus de 60 secondes. La page demandée est un script PHP

J'ai passé plusieurs jours à essayer de trouver des réponses et à essayer tout ce que je peux trouver sur Internet, y compris plusieurs entrées ici sur Stack Overflow, rien ne fonctionne.

J'ai essayé de modifier les paramètres PHP, les paramètres PHP-FPM et les paramètres Nginx. Vous pouvez voir une question que j'ai posée vendredi sur les forums NginX ( http://forum.nginx.org/read.php?9,237692 ), mais qui n'a pas reçu de réponse. J'espère que je pourrais être capable de trouver une réponse ici avant que je ne sois forcé de revenir à Apache, ce qui, je le sais, ne fonctionne que.

Ce n'est pas le même problème que les erreurs HTTP 500 signalées dans d'autres entrées.

J'ai pu reproduire le problème avec une nouvelle instance micro AWS de NginX à l'aide de PHP 5.4.11.

Pour aider ceux qui souhaitent voir le problème en action, je vais vous expliquer la configuration que j'ai exécutée pour le dernier serveur de test Micro.

Vous devrez lancer une nouvelle instance AWS Micro (donc gratuite) à l'aide de l'AMI ami-c1aaabb5.

Cette entrée Pastebin a la configuration complète à exécuter pour refléter mon environnement de test. Vous aurez juste besoin de changer example.com dans la configuration de NginX à la fin.

http://Pastebin.com/WQX4AqEU

Une fois cette configuration terminée, il vous suffit de créer le fichier exemple PHP que je teste et qui est

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

Enregistrez cela dans la racine Web, puis testez. Si vous exécutez le script à partir de la ligne de commande en utilisant php ou php-cgi, cela fonctionnera. Si vous accédez au script via une page Web et réduisez le journal d'accès {/var/log/nginx/example.access.log, vous remarquerez que vous recevez la réponse HTTP 1.1 499 après 60 secondes.

Maintenant que vous pouvez voir le délai d'attente, je vais passer en revue certaines des modifications de configuration que j'ai apportées à la fois à PHP et à NginX pour essayer de résoudre ce problème. Pour PHP, je créerai plusieurs fichiers de configuration afin de pouvoir les désactiver facilement.

Mise à jour de la configuration FPM PHP pour inclure les fichiers de configuration externes

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

Créer une nouvelle configuration PHP-FPM pour remplacer le délai d'attente de la requête

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

Modifier certains paramètres globaux pour que l'intervalle de redémarrage d'urgence soit de 2 minutes

# 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

Ensuite, nous allons modifier certains paramètres PHP.INI, en utilisant à nouveau des fichiers séparés.

# 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

Comme vous pouvez le constater, cela augmente le délai d'attente du socket à 3 minutes et aidera à consigner les erreurs.

Enfin, je vais modifier certains paramètres de NginX pour augmenter le côté temporisé

D'abord, j'édite le fichier /etc/nginx/nginx.conf et l'ajoute à la directive http fastcgi_read_timeout 300;

Ensuite, j'édite le fichier / etc/nginx/sites-enabled/example que nous avons créé précédemment (voir l'entrée Pastebin) et ajoute les paramètres suivants à la directive server.

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;

Enfin, j’ajoute ce qui suit dans la section location ~ .php $ du répertoire du serveur.

fastcgi_read_timeout 360;
fastcgi_send_timeout 360;
fastcgi_connect_timeout 1200;

Avant de réessayer le script, démarrez nginx et php-fpm pour vous assurer que les nouveaux paramètres ont été repris. J'essaie ensuite d'accéder à la page et je reçois toujours l'entrée HTTP/1.1 499 dans le fichier exemple.error.log de NginX.

Alors, où est-ce que je vais mal? Cela ne fonctionne que sur Apache lorsque je règle le temps d'exécution maximal de PHP à 2 minutes.

Je peux voir que les paramètres PHP ont été récupérés en exécutant phpinfo () à partir d'une page accessible par le Web. Je ne comprends tout simplement pas, je pense en fait que trop a été augmenté car il aurait simplement besoin de max_execution_time, default_socket_timeoutde PHP ainsi que de fastcgi_read_timeout de NginX au sein de juste la directive server-> location.

Mise à jour 1

Après avoir effectué quelques tests supplémentaires pour montrer que le problème n’est pas que le client est en train de mourir, j’ai modifié le fichier de test pour le mettre à jour.

<?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');
?>

Si j'exécute le script à partir d'une page Web, le contenu du fichier doit être défini sur la première chaîne. 60 secondes plus tard, l'erreur apparaît dans le journal NginX. 10 secondes plus tard, le contenu du fichier passe à la 2ème chaîne, ce qui prouve que PHP termine le processus.

Mise à jour 2

Activer fastcgi_ignore_client_abort; modifie la réponse d'un HTTP 499 en un HTTP 200 bien que rien ne soit toujours renvoyé au client final.

Mise à jour 3

Après avoir installé Apache et PHP (5.3.10) directement sur la boîte de dialogue (avec apt), puis augmenté le temps d'exécution, le problème semble également se produire également sur Apache. Les symptômes sont les mêmes que NginX maintenant, une réponse HTTP200 mais la connexion client réelle expire avant la main.

J'ai également commencé à remarquer, dans les journaux de NginX, que si je testais avec Firefox, il effectuait une double requête (comme ceci PHP, le script s'exécute deux fois lorsqu'il dépasse 60 secondes ). Bien que cela semble être le client qui demande l'échec du script

51
TFAtTheMoon

Le problème est dû à Elastic Load Balancers sur AWS. Par défaut, ils expirent après 60 secondes d'inactivité, ce qui était à l'origine du problème.

Donc, ce n'était pas NginX, PHP-FPM ou PHP mais l'équilibreur de charge.

Pour résoudre ce problème, allez simplement dans l'onglet "Description" d'ELB, faites défiler vers le bas, puis cliquez sur le lien "(Modifier)" en regard de la valeur "Délai d'inactivité: 60 secondes"

59
TFAtTheMoon

Je pensais que je laisserais mes deux cents. D'abord, le problème n'est pas lié à php (ça pourrait toujours être un php, php me surprend toujours: P). Cest sûr. Cela est principalement dû à un serveur mandaté par lui-même, plus précisément à un problème de noms d’hôte/alias. Dans votre cas, il se pourrait que l’équilibreur de charge demande nginx et que nginx l’appelle, ce qui continue. 

J'ai rencontré un problème similaire avec nginx en tant qu'équilibreur de charge et Apache en tant que serveur Web/proxy.

1
Waheed

Je ne suis pas sûr que quelqu'un d'autre ait été confronté à cela, mais pour moi, c'est arrivé après que j'ai mis un / à la fin de l'URL de mon instance. Ceci a donné une erreur 499 et seulement après avoir supprimé le /, il m'en a donné 200 et tout s'est bien passé.

0
Souvik Ray

En fait, j’ai rencontré le même problème sur un serveur et j’ai compris qu’après les changements apportés à la configuration de nginx, je n’avais pas redémarré le serveur nginx. C’est pourquoi chaque fois que nginx url a été lu, j’ai reçu une réponse de 499 http. Après le redémarrage de nginx, il a commencé à fonctionner correctement avec les réponses http 200.

0
Rajeev kumar

Vous devez trouver dans quel endroit vivre problème. Je ne connais pas la réponse exacte, mais essayons simplement de la trouver.

Nous avons ici 3 éléments: nginx, php-fpm, php. Comme vous l'avez dit, les mêmes paramètres php sous Apache sont acceptables. Est-ce que c'est même pas la même configuration? Avez-vous essayé Apache au lieu de nginx sur le même système d'exploitation/hôte/etc.?

Si nous verrons que php n'est pas suspect, nous avons deux suspects: nginx et php-fpm.

Pour exclure nginx: essayez d’installer le même "système" sur Ruby. Voir https://github.com/garex/puppet-module-nginx pour avoir l’idée d’installer la plus simple des configurations Ruby. Ou utilisez google (peut-être que ce sera encore mieux).

Mon principal suspect ici est php-fpm.

Essayez de jouer avec ces paramètres:

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