Proxy inverso de Nginx que causa el tiempo de espera de 504 Gateway

128

Estoy usando Nginx como un proxy inverso que toma solicitudes y luego hace un proxy_pass para obtener la aplicación web real del servidor ascendente que se ejecuta en el puerto 8001.

Si voy a mywebsite.com o hago un wget, obtengo un 504 Gateway Timeout después de 60 segundos ... Sin embargo, si cargo mywebsite.com:8001, ¡la aplicación se carga como se esperaba!

Entonces, algo impide que Nginx se comunique con el servidor ascendente.

Todo esto comenzó después de que mi empresa de alojamiento reiniciara la máquina en la que mis cosas se estaban ejecutando, antes de eso no hubo ningún problema.

Aquí está mi bloque de servidor 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;
    }
} 

Y la salida de mi registro de errores de 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
fuente
¿El servidor ejecuta SELinux?
CrackerJack9
EN MI CASO, la puerta de enlace NAT era el problema, no el NGINX o la API de back-end. stackoverflow.com/a/62351959/9956279
Sushilinux

Respuestas:

152

Probablemente pueda agregar algunas líneas más para aumentar el período de tiempo de espera en sentido ascendente. Los siguientes ejemplos establecen el tiempo de espera en 300 segundos:

proxy_connect_timeout       300;
proxy_send_timeout          300;
proxy_read_timeout          300;
send_timeout                300;
usuario2540984
fuente
55
Creo que aumentar el tiempo de espera rara vez es la respuesta a menos que sepa que su red / servicio responderá siempre o, en algunos casos, muy lentamente. Pocas solicitudes web hoy en día deberían tomar más de unos segundos a menos que esté descargando contenido (archivos / imágenes)
Almund
@Almund Pensé lo mismo (casi no me molesté en intentar esto), pero por alguna razón esto simplemente funcionó para mí. (Anteriormente se agotó el tiempo de espera después de 60 segundos, ahora obtenga respuesta inmediatamente).
Dax Fohl
@Dax Fohl: Eso es curioso. Extraje la fuente y eché un vistazo rápido y, por lo que puedo ver, establecer cualquier configuración de proxy_pass aparte de proxy_pass inicializará un montón de configuraciones que supongo que ejecutarán el proxy de una manera diferente, por lo que tal vez configurar cualquier cosa dará esto mismo comportamiento.
Almund
No resolvió el problema para mí usarlo con un servidor nodejs
vpx
3
Me parece que solo necesito proxy_read_timeoutcuando se depura en el backend. ¡Gracias!
Jeff Puckett
79

Es probable que aumentar el tiempo de espera no resuelva el problema, ya que, como usted dice, el servidor web de destino real responde muy bien.

Tuve este mismo problema y descubrí que tenía que ver con no usar un keep-alive en la conexión. Realmente no puedo responder por qué esto es así, pero al borrar el encabezado de la conexión, resolví este problema y la solicitud fue aprobada correctamente:

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;
    }
}

Eche un vistazo a estas publicaciones que lo explican con más detalle: nginx cierra la conexión aguas arriba después de solicitar la aclaración del encabezado Keep-alive http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive

Almund
fuente
77
MESES de problemas resueltos por una sola línea proxy_set_header Connection "";jajaja, no uses runcloud
asiente con la cabeza
21

user2540984 , así como muchos otros, han señalado que puede intentar aumentar su configuración de tiempo de espera. Yo mismo enfrenté un problema similar a este e intenté cambiar mi configuración de tiempo de espera en el archivo /etc/nginx/nginx.conf , como sugieren casi todos en estos hilos. Esto, sin embargo, no me ayudó un poco; no hubo cambios aparentes en la configuración de tiempo de espera de NGINX. Después de muchas horas de búsqueda, finalmente logré resolver mi problema.

La solución se encuentra en este hilo del foro , y lo que dice es que debe poner su configuración de tiempo de espera en /etc/nginx/conf.d/timeout.conf (y si este archivo no existe, debe crearlo). Usé la misma configuración que se sugiere en el hilo:

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

Puede que esta no sea la solución a su problema particular, pero si alguien más se da cuenta de que el tiempo de espera cambia en /etc/nginx/nginx.conf no haga nada, ¡espero que esta respuesta ayude!

Andreas Forslöw
fuente
hola no hay timeout.conf en mi directorio config.d. Dijiste crearlo, y quiero confirmarlo solo agrega la configuración anterior en el timeout.conf?
tktktk0711
Sí, solo agrégalos. Puede modificarlos para sus propias necesidades, ¡pero estos funcionaron para mí!
Andreas Forslöw el
Desafortunadamente, en la granja de Laravel con ubuntu y Nginx, esto no funciona. :( ¿Quiere decir simplemente agregar esas líneas? Sin server{}o algo más? Este error aparece justo después de 5 minutos. Vuelvo a cargar, reinicio, y nunca pasa más allá de esos 5 minutos o 300 segundos. ¿Hay más ideas para arreglar? ¿verdad?
Patros
15

Si desea aumentar o agregar un límite de tiempo a todos los sitios, puede agregar las líneas siguientes al nginx.confarchivo.

Agregue las siguientes líneas a la httpsección /usr/local/etc/nginx/nginx.confo al /etc/nginx/nginx.confarchivo.

fastcgi_read_timeout 600;
proxy_read_timeout 600;

Si las líneas anteriores no existen en el confarchivo, agréguelas, de lo contrario, aumente fastcgi_read_timeouty proxy_read_timeoutasegúrese de que nginx y php-fpm no se hayan agotado.

Para aumentar el límite de tiempo para un solo sitio, puede editar en 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; 
}

y después de agregar estas líneas nginx.conf, no olvides reiniciar nginx.

service php7-fpm reload 
service nginx reload

o, si está utilizando valet, simplemente escriba valet restart.

Adeel
fuente
1
Gracias funciona para mí:fastcgi_read_timeout 600; proxy_read_timeout 600;
Alejandro
13

También puede enfrentar esta situación si su servidor ascendente utiliza un nombre de dominio y su dirección IP cambia (por ejemplo: su servidor ascendente apunta a un balanceador de carga elástica AWS)

El problema es que nginx resolverá la dirección IP una vez y la mantendrá en caché para solicitudes posteriores hasta que se vuelva a cargar la configuración.

Puede decirle a nginx que use un servidor de nombres para volver a resolver el dominio una vez que la entrada en caché caduque:

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;
}

Los documentos en proxy_pass explican por qué funciona este truco:

El valor del parámetro puede contener variables. En este caso, si se especifica una dirección como nombre de dominio, el nombre se busca entre los grupos de servidores descritos y, si no se encuentra, se determina mediante un resolutor.

Felicitaciones a "Nginx con flujos ascendentes dinámicos" (tenzer.dk) por la explicación detallada, que también contiene información relevante sobre una advertencia de este enfoque con respecto a los URI reenviados.

el.atomo
fuente
1
Esta respuesta es oro, exactamente lo que me pasó. aguas arriba apunta a aws elb y todo el tiempo de espera repentino de Gateway.
Nathan Do
2

Tuve el mismo problema Resultó que fue causado por el seguimiento de la conexión de iptables en el servidor ascendente. Después de eliminar --state NEW,ESTABLISHED,RELATEDel script de firewall y enjuagarse con conntrack -Fel problema desapareció.

mindlab
fuente
0

NGINX en sí mismo puede no ser la causa raíz.

SI los "puertos mínimos por instancia de VM" establecidos en la puerta de enlace NAT, que se interponen entre su instancia de NGINX y el proxy_passdestino, son demasiado pequeños para la cantidad de solicitudes simultáneas, debe incrementarse.

Solución: aumente la cantidad de puertos disponibles por VM en NAT Gateway.

Contexto En mi caso, en Google Cloud, se colocó un proxy inverso NGINX dentro de una subred, con una puerta de enlace NAT. La instancia de NGINX estaba redirigiendo solicitudes a un dominio asociado con nuestra API de back-end (ascendente) a través de NAT Gateway.

Esta documentación de GCP lo ayudará a comprender cómo NAT es relevante para el tiempo de espera de NGINX 504.

Sushilinux
fuente
-1

En mi caso, reinicio php para y se volvió correcto.

Mahdy Aslamy
fuente