with deploy con aws and django nginx deployment fastcgi

deploy - Cómo reiniciar graciosamente django ejecutando fcgi detrás de nginx?



django gunicorn nginx supervisord (5)

Estoy ejecutando una instancia de django detrás de nginx conectado usando fcgi (usando el comando manage.py runfcgi). Dado que el código se carga en la memoria, no puedo volver a cargar el nuevo código sin matar y reiniciar los procesos django fcgi, interrumpiendo así el sitio web en vivo. El reinicio en sí mismo es muy rápido. Pero al matar los procesos de fcgi, primero se interrumpirán las acciones de algunos usuarios, lo que no es bueno. Me pregunto cómo puedo volver a cargar el nuevo código sin causar ninguna interrupción. ¡Los consejos serán muy apreciados!


¡Finalmente encontramos la solución adecuada para esto!

http://rambleon.usebox.net/post/3279121000/how-to-gracefully-restart-django-running-fastcgi

Primero envíe una señal HUP para señalar un reinicio. Flup hará esto con todos sus hijos:

  1. cierra el zócalo que detendrá a los niños inactivos
  2. envía una señal INT
  3. espera 10 segundos
  4. envía una señal KILL

Cuando todos los niños se hayan ido, comenzará nuevos.

Esto funciona casi todo el tiempo, excepto que si un niño está manejando una solicitud cuando flup ejecuta el paso 2 entonces su servidor morirá con KeyboardInterrupt , lo que le da al usuario un error de 500.

La solución es instalar un controlador SIGINT; consulte la página anterior para obtener más información. Incluso ignorar SIGINT le da a su proceso 10 segundos para salir, lo cual es suficiente para la mayoría de las solicitudes.


Así que seguí e implementé la sugerencia de Martin. Aquí está el script bash que se me ocurrió.

pid_file=/path/to/pidfile port_file=/path/to/port_file old_pid=`cat $pid_file` if [[ -f $port_file ]]; then last_port=`cat $port_file` port_to_use=$(($last_port + 1)) else port_to_use=8000 fi # Reset so me don''t go up forever if [[ $port_to_use -gt 8999 ]]; then port_to_use=8000 fi sed -i "s/$old_port/$port_to_use/g" /path/to/nginx.conf python manage.py runfcgi host=127.0.0.1 port=$port_to_use maxchildren=5 maxspare=5 minspare=2 method=prefork pidfile=$pid_file echo $port_to_use > $port_file kill -HUP `cat /var/run/nginx.pid` echo "Sleeping for 5 seconds" sleep 5s echo "Killing old processes on $last_port, pid $old_pid" kill $old_pid


Comenzaría un nuevo proceso fcgi en un nuevo puerto, cambiaría la configuración de nginx para usar el nuevo puerto, tendría la configuración de recarga de nginx (que en sí misma es elegante), y luego detendría el proceso anterior (puede usar netstat para averiguar cuándo la última conexión al viejo puerto está cerrada).

Alternativamente, puede cambiar la implementación fcgi para bifurcar un nuevo proceso, cerrar todos los sockets en el hijo excepto el socket del servidor fcgi, cerrar el socket del servidor fcgi en parent, ejecutar un nuevo proceso django en el hijo (haciendo que use el servidor fcgi socket) y finaliza el proceso principal una vez que todas las conexiones fcgi están cerradas. IOW, implementa un elegante reinicio para runfcgi.


Encontré esta página mientras buscaba una solución para este problema. Todo lo demás falló, así que busqué el código fuente :)

La solución parece ser mucho más simple. El servidor Django fcgi usa flup, que maneja la señal HUP de la forma correcta: se apaga con gracia. Entonces, todo lo que tienes que hacer es:

  1. envíe la señal HUP al servidor fcgi (el argumento pidfile = de runserver será útil)

  2. espere un poco (el flup permite que los niños procesen 10 segundos, así que espere un par más; 15 parece un buen número)

  3. envió la señal KILL al servidor fcgi, en caso de que algo lo bloqueara

  4. arranca el servidor de nuevo

Eso es.