Arreglar errores 502 con nginx y PHP-FPM

Hace algún tiempo, un servidor comenzó a generar errores 502: Bad Gateway de manera aleatoria y no reproducible. O sea, en las condiciones ideales para convertirse en un quebradero de cabeza.

Este servidor funciona con nginx + PHP-FPM, pero luego de descartar las razones más usuales de problemas que se pueden encontrar en este tipo de configuraciones, los errores seguían ocurriendo. Lo peor es que el servicio no solamente se interrumpía, sino que no volvía a funcionar hasta reiniciar manualmente nginx.

Finalmente pude dar con la causa: al parecer, habían ciertos procesos de PHP que nunca terminaban adecuadamente. Si bien el valor de max_execution_time estaba correctamente configurado, en ciertas condiciones hay procesos que no terminan de ejecutarse correctamente. La solución, de parte de PHP:

; detener la ejecución que no obedecen a max_execution_timerequest_terminate_timeout = 30s

; loguear peticiones con tiempo de ejecución excesivo
slowlog = /var/log/php5-fpm/$pool.log.slow
request_slowlog_timeout = 30s

Luego, por parte de nginx también es recomendable establecer límites a la conexión que hace el servidor web con el servidor FastCGI (en este caso, PHP-FPM)

http {
    ...
    # fix para "upstream sent too big header"
    fastcgi_buffers 8 16k;
    fastcgi_buffer_size 32k;
    # timeout para conexiones entre nginx y fastcgi
    fastcgi_connect_timeout 30s;
    fastcgi_send_timeout 30s;
    fastcgi_read_timeout 30s;
    ...
}

Algunas notas:

  • Según la documentación de nginx, el valor fasctgi_connect_timeout no debiese exceder los 75 segundos
  • Para fastcgi_send_timeout y fastcgi_read_timeout, el tiempo máximo se mide entre dos operaciones de escritura/lectura simultáneas, respectivamente, y no considera el tiempo de transmisión de datos. Es decir, si tras el lapso de tiempo indicado el servidor FastCGI no recibe/envía ningún dato, se corta la conexión.