Saltar al contenido principal

Guías / Códigos de estado HTTP explicados

502 Bad Gateway: qué se rompió detrás del proxy y cómo encontrarlo

Un 502 Bad Gateway significa que un proxy delante de tu sitio le pidió una respuesta al backend y obtuvo algo inválido, o nada en absoluto. El proxy está funcionando correctamente; está reportando que lo que hay detrás está caído, se ha colgado o habla el protocolo equivocado.

Quién devuelve un 502 y por qué

El RFC 9110 define el 502 para un servidor que actúa como puerta de enlace o proxy y recibió una respuesta inválida de un servidor entrante al que accedió mientras intentaba cumplir la petición. Todo stack moderno tiene al menos un salto así: nginx o Apache delante de un servidor de aplicación, un balanceador de carga delante de una flota, una CDN delante de tu origen, o los tres.

Esa disposición en capas es la clave para leer un 502. El componente que respondió está lo bastante sano como para generar una página de error. El componente detrás no lo está. Así que un 502 siempre divide tu stack en una mitad que funciona y una mitad rota, y tu trabajo es averiguar dónde está el límite.

Sus vecinos dicen algo más concreto. Un 504 Gateway Timeout significa que el backend era accesible pero demasiado lento. Un 500 significa que el propio backend se ejecutó y lanzó un error. Un 502 significa que el backend dio una respuesta mala o ninguna respuesta en absoluto. La comparación completa está en el resumen de la familia 5xx.

Causas habituales

  • El proceso del backend no se está ejecutando. Un servidor de aplicación caído, un pool de PHP-FPM detenido, un contenedor que salió o falló su comprobación de salud. El proxy conecta a un puerto en el que nadie está escuchando.
  • El backend se cayó a mitad de la petición. Un cierre por falta de memoria o un fallo de segmentación cierra la conexión antes de que se completen las cabeceras de la respuesta.
  • Dirección o puerto de upstream equivocados. Una configuración que apunta al puerto antiguo después de un cambio, o a un host que ya no resuelve.
  • Desajuste de protocolo. El proxy habla HTTP plano a un puerto que espera TLS, o al revés. Los bytes no se pueden interpretar, así que el proxy considera la respuesta inválida.
  • Cabeceras de respuesta demasiado grandes. Una cookie sobredimensionada o una cabecera inusualmente larga supera el búfer del proxy, y la respuesta se rechaza en lugar de reenviarse.
  • Desajuste de keep-alive. El proxy reutiliza una conexión inactiva que el backend ya ha cerrado, produciendo 502 esporádicos bajo una carga por lo demás normal.
  • Reinicios y despliegues. Cualquier ventana en la que el proceso antiguo ya se ha detenido y el nuevo todavía no acepta conexiones.
  • Todos los backends no sanos. Un balanceador de carga sin ningún miembro que pase la comprobación no tiene adónde enviar la petición.

Leer el registro del proxy, que suele terminar la investigación

El código de estado es genérico, pero la línea del registro del proxy es específica. Con nginx, estos son los mensajes que merece la pena reconocer:

[error] connect() failed (111: Connection refused) while connecting to upstream,
        upstream: "http://127.0.0.1:8080/"

[error] upstream prematurely closed connection while reading response header
        from upstream

[error] recv() failed (104: Connection reset by peer) while reading response
        header from upstream

[error] upstream sent too big header while reading response header from upstream

[error] no live upstreams while connecting to upstream

Cada uno señala a un sitio distinto:

  • connect() failed (111: Connection refused). Nada está escuchando en esa dirección y puerto. El backend está detenido, vinculado a otra interfaz, o en un puerto distinto del que dice la configuración.
  • upstream prematurely closed connection. El backend aceptó la petición y luego murió o colgó antes de terminar la respuesta. Busca caídas, cierres por falta de memoria o un tiempo de espera agotado de un worker dentro de la aplicación, no en nginx.
  • connection reset by peer. Parecido, pero la conexión se reinició de forma activa. A menudo un firewall de por medio, o un backend que cerró una conexión de un pool que el proxy todavía consideraba abierta.
  • upstream sent too big header. Un problema de tamaño de búfer en el proxy, no un fallo en el backend. La respuesta es válida pero más grande de lo que el proxy está configurado para guardar.
  • no live upstreams. Las comprobaciones de salud han marcado como caído a todos los backends.

Cómo arreglarlo

  1. Prueba el backend directamente, saltándote el proxy. Desde el host del proxy, pide la propia dirección de upstream:
    curl -sS -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8080/
    Un 200 aquí con un 502 en la URL pública significa que el fallo está en la configuración del proxy o en el enlace entre los dos. Una conexión rechazada significa que el backend realmente está caído.
  2. Comprueba que el backend se está ejecutando y escuchando en la dirección que espera el proxy. Vincularse a 127.0.0.1 cuando el proxy marca a una dirección de contenedor es una causa frecuente.
  3. Lee el registro de errores del proxy y haz coincidir el mensaje con la lista de arriba antes de cambiar ninguna configuración.
  4. Luego lee el registro del backend. Una caída, un cierre por falta de memoria o un tiempo de espera agotado de un worker en el mismo segundo confirma el caso de "prematurely closed". El silencio apunta de vuelta a la conectividad.
  5. Verifica la dirección, el puerto y el esquema del upstream en la configuración del proxy, sobre todo tras una migración o una reconstrucción de contenedor.
  6. Sube los búferes de cabecera del proxy si el registro dice que la cabecera era demasiado grande, y por separado averigua por qué creció la cabecera.
  7. Haz que los despliegues se solapen. Arranca el proceso nuevo, espera a que pase una comprobación de salud, y luego drena y detén el antiguo. Las actualizaciones progresivas con puerta de salud eliminan por completo la ventana de reinicio que causa los 502 en tiempo de despliegue.

Detectar un 502 que dura veinte segundos

Los 502 en tiempo de despliegue y por bucles de caída son cortos. Un backend se reinicia, falla durante veinte segundos y se recupera, así que para cuando alguien lo comprueba el sitio está bien y no queda nada que mirar. Una comprobación HTTP programada que se ejecuta de forma continua registra esas ventanas con marcas de tiempo, lo que convierte "esta mañana estuvo raro un momento" en un patrón que puedes correlacionar con despliegues y reinicios. Un 502 también puede venir de un borde de CDN en lugar de tu origen, así que comprobar desde varias regiones separa un fallo global del backend de un problema de borde que afecta a parte de tu tráfico, que es para lo que sirve la monitorización de disponibilidad distribuida.

Compruébalo ahora

Ejecuta la comprobación gratuita en tu propio sitio, sin necesidad de cuenta.

HTTP check

Monitoriza esto de forma permanente

Recibe un aviso en cuanto algo falle: HostTracker comprueba desde más de 300 ubicaciones y te avisa por correo, SMS, Slack, Telegram y más.

Funciones de HostTracker

Más en esta sección: Códigos de estado HTTP explicados