Proxy inverse Nginx provoquant un délai d'expiration de la passerelle 504

130

J'utilise Nginx comme proxy inverse qui prend les demandes puis effectue un proxy_pass pour obtenir l'application Web réelle du serveur en amont fonctionnant sur le port 8001.

Si je vais sur mywebsite.com ou que je fais un wget, j'obtiens un délai d'expiration de la passerelle 504 après 60 secondes ... Cependant, si je charge mywebsite.com:8001, l'application se charge comme prévu!

Donc, quelque chose empêche Nginx de communiquer avec le serveur en amont.

Tout cela a commencé après que ma société d'hébergement a réinitialisé la machine sur laquelle mes affaires fonctionnaient, avant cela, aucun problème.

Voici mon bloc serveur vhosts:

server {
    listen   80;
    server_name mywebsite.com;

    root /home/user/public_html/mywebsite.com/public;

    access_log /home/user/public_html/mywebsite.com/log/access.log upstreamlog;
    error_log /home/user/public_html/mywebsite.com/log/error.log;

    location / {
        proxy_pass http://xxx.xxx.xxx.xxx:8001;
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
} 

Et la sortie de mon journal des erreurs Nginx:

2014/06/27 13:10:58 [error] 31406#0: *1 upstream timed out (110: Connection timed out) while connecting to upstream, client: xxx.xx.xxx.xxx, server: mywebsite.com, request: "GET / HTTP/1.1", upstream: "http://xxx.xxx.xxx.xxx:8001/", host: "mywebsite.com"
Dave Roma
la source
Le serveur exécute-t-il SELinux?
CrackerJack9
DANS MON CAS, la passerelle NAT était le problème, pas le NGINX ou l'API backend. stackoverflow.com/a/62351959/9956279
Sushilinux

Réponses:

152

Peut probablement ajouter quelques lignes supplémentaires pour augmenter le délai d'expiration vers l'amont. Les exemples ci-dessous définissent le délai d'expiration à 300 secondes:

proxy_connect_timeout       300;
proxy_send_timeout          300;
proxy_read_timeout          300;
send_timeout                300;
user2540984
la source
5
Je pense que l'augmentation du délai d'attente est rarement la réponse à moins que vous ne sachiez que votre réseau / service répondra toujours ou dans certains cas très lentement. De nos jours, peu de requêtes Web devraient prendre plus de quelques secondes à moins que vous ne téléchargiez du contenu (fichiers / images)
Almund
@Almund J'ai pensé la même chose (je n'ai presque pas pris la peine d'essayer ça), mais pour une raison quelconque, cela a fonctionné pour moi. (Auparavant expiré après 60 secondes, obtenez maintenant une réponse immédiatement).
Dax Fohl
@Dax Fohl: C'est curieux. J'ai extrait la source et jeté un coup d'œil rapide et d'après ce que je peux voir, la définition de tout proxy_ mis à part le proxy_pass initialisera un tas de paramètres qui, je suppose, exécuteront le proxy d'une manière différente, alors peut-être que la configuration de quelque chose donnera la même chose comportement.
Almund
N'a pas résolu le problème pour moi en l'utilisant avec un serveur nodejs
vpx
3
Je trouve que je n'ai besoin que du proxy_read_timeoutlors du débogage sur le backend. Merci!
Jeff Puckett
79

L'augmentation du délai d'expiration ne résoudra probablement pas votre problème car, comme vous le dites, le serveur Web cible réel répond très bien.

J'ai eu ce même problème et j'ai trouvé que cela avait à voir avec le fait de ne pas utiliser de keep-alive sur la connexion. Je ne peux pas vraiment répondre pourquoi mais, en effaçant l'en-tête de connexion, j'ai résolu ce problème et la demande a été envoyée par proxy très bien:

server {
    location / {
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   Host      $http_host;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_pass http://localhost:5000;
    }
}

Jetez un œil à ces articles qui l'expliquent plus en détail: nginx ferme la connexion en amont après la demande Clarification de l'en-tête Keep-alive http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive

Almund
la source
7
MOIS de problèmes résolus par une seule ligne proxy_set_header Connection "";lol, n'utilisez pas runcloud
nodws
22

user2540984 , ainsi que beaucoup d'autres ont souligné que vous pouvez essayer d'augmenter vos paramètres de délai d'expiration. J'ai moi-même été confronté à un problème similaire à celui-ci et j'ai essayé de modifier mes paramètres de délai d'expiration dans le fichier /etc/nginx/nginx.conf , comme le suggèrent presque tout le monde dans ces threads. Cela ne m'a cependant pas aidé du tout; il n'y avait aucun changement apparent dans les paramètres de délai d'expiration de NGINX. Après de nombreuses heures de recherche, j'ai finalement réussi à résoudre mon problème.

La solution réside dans ce fil de discussion du forum , et ce qu'il dit, c'est que vous devez mettre vos paramètres de délai d'expiration dans /etc/nginx/conf.d/timeout.conf (et si ce fichier n'existe pas, vous devez le créer). J'ai utilisé les mêmes paramètres que ceux suggérés dans le fil:

proxy_connect_timeout 600;
proxy_send_timeout 600;
proxy_read_timeout 600;
send_timeout 600;

Ce n'est peut-être pas la solution à votre problème particulier, mais si quelqu'un d'autre remarque que les changements de délai dans /etc/nginx/nginx.conf ne font rien, j'espère que cette réponse vous aidera!

Andreas Forslöw
la source
salut il n'y a pas de timeout.conf dans mon répertoire config.d. Vous avez dit de le créer, et je veux le confirmer, ajoutez simplement le paramètre ci-dessus dans timeout.conf?
tktktk0711
Oui, ajoutez-les simplement. Vous pouvez les modifier pour vos propres besoins, mais cela a fonctionné pour moi!
Andreas Forslöw
Malheureusement, dans la ferme de Laravel avec ubuntu et Nginx, cela ne fonctionne pas. :( Voulez-vous simplement ajouter ces lignes? Sans server{}ou autre chose? Cette erreur survient juste après 5 minutes. Je recharge, redémarre et elle ne dépasse jamais ces 5 minutes ou 300 secondes. Y a-t-il d'autres idées à corriger ça?
Pathros
15

Si vous souhaitez augmenter ou ajouter une limite de temps à tous les sites, vous pouvez ajouter des lignes ci-dessous au nginx.conffichier.

Ajoutez les lignes ci-dessous à la httpsection du fichier /usr/local/etc/nginx/nginx.confou /etc/nginx/nginx.conf.

fastcgi_read_timeout 600;
proxy_read_timeout 600;

Si les lignes ci-dessus n'existent pas dans le conffichier, ajoutez-les, sinon augmentez fastcgi_read_timeoutet proxy_read_timeoutassurez-vous que nginx et php-fpm n'ont pas expiré.

Pour augmenter la limite de temps pour un seul site, vous pouvez modifier dans vim /etc/nginx/sites-available/example.com

location ~ \.php$ {
    include /etc/nginx/fastcgi_params;
        fastcgi_pass  unix:/var/run/php5-fpm.sock;
    fastcgi_read_timeout 300; 
}

et après avoir ajouté ces lignes nginx.conf, n'oubliez pas de redémarrer nginx.

service php7-fpm reload 
service nginx reload

ou, si vous utilisez un valet, tapez simplement valet restart.

Adeel
la source
1
Merci travaille pour moi:fastcgi_read_timeout 600; proxy_read_timeout 600;
Alejandro
13

Vous pouvez également faire face à cette situation si votre serveur en amont utilise un nom de domaine et que son adresse IP change (par exemple: votre amont pointe vers un AWS Elastic Load Balancer)

Le problème est que nginx résoudra l'adresse IP une fois et la conservera en cache pour les demandes suivantes jusqu'à ce que la configuration soit rechargée.

Vous pouvez dire à nginx d'utiliser un serveur de noms pour résoudre à nouveau le domaine une fois que l'entrée mise en cache expire:

location /mylocation {
    # use google dns to resolve host after IP cached expires
    resolver 8.8.8.8;
    set $upstream_endpoint http://your.backend.server/;
    proxy_pass $upstream_endpoint;
}

La documentation sur proxy_pass explique pourquoi cette astuce fonctionne:

La valeur du paramètre peut contenir des variables. Dans ce cas, si une adresse est spécifiée comme nom de domaine, le nom est recherché parmi les groupes de serveurs décrits et, s'il n'est pas trouvé, est déterminé à l'aide d'un résolveur.

Félicitations à "Nginx avec amont dynamique" (tenzer.dk) pour l'explication détaillée, qui contient également des informations pertinentes sur une mise en garde de cette approche concernant les URI transmis.

el.atomo
la source
1
cette réponse est en or, exactement ce qui m'est arrivé. en amont pointe vers aws elb et tout le délai d'expiration de la passerelle.
Nathan le
2

Avait le même problème. Il s'est avéré que cela était dû au suivi de la connexion iptables sur le serveur en amont. Après la suppression --state NEW,ESTABLISHED,RELATEDdu script de pare-feu et le nettoyage conntrack -Fdu problème, le problème a disparu.

mindlab
la source
0

NGINX lui-même n'est peut-être pas la cause première.

SI "les ports minimum par instance de VM" définis sur la passerelle NAT - qui se trouvent entre votre instance NGINX et la proxy_passdestination - sont trop petits pour le nombre de requêtes simultanées, il doit être augmenté.

Solution: augmentez le nombre de ports disponibles par VM sur la passerelle NAT.

Contexte Dans mon cas, sur Google Cloud, un proxy inverse NGINX a été placé dans un sous-réseau, avec une passerelle NAT. L'instance NGINX redirigeait les demandes vers un domaine associé à notre API backend (en amont) via la passerelle NAT.

Cette documentation de GCP vous aidera à comprendre comment NAT est pertinent pour le délai d'expiration du NGINX 504.

Sushilinux
la source
-1

Dans mon cas, je redémarre php pour et cela devient ok.

Mahdy Aslamy
la source