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!Cómo reiniciar graciosamente django ejecutando fcgi detrás de nginx?
Respuesta
Comenzaría un nuevo proceso fcgi en un nuevo puerto, cambiaría la configuración nginx para usar el nuevo puerto, tendría la configuración de recarga nginx (que en sí misma es elegante), y luego detendría el proceso anterior (puede usar netstat para averiguar cuándo está cerrada la última conexión al puerto anterior).
Alternativamente, puede cambiar la implementación de 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 el padre, ejecutar un nuevo proceso django en el hijo (hacerlo use el socket del servidor fcgi) y finalice el proceso principal una vez que se cierren todas las conexiones de fcgi. IOW, implementa un elegante reinicio para runfcgi.
Se puede utilizar en lugar de desove FastCGI
Así que siguió adelante e implementado 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
wow, simple pero increíblemente útil. ¡Muchas gracias por compartir esto! – srchulo
Encontré esta página mientras buscaba una solución para este problema. Todo lo demás falló, así que busqué en 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. Así que todo lo que tiene que hacer es:
enviar la señal HUP al servidor fcgi (el archivo pid = argumento de ejecución del servidor será muy útil)
esperar un poco (flup permite a los niños procesos 10 segundo, por lo que esperar un par más; 15 parece un buen número)
envió la señal KILL al servidor fcgi, si acaso algo, estuvo muy
empezar de nuevo el servidor
Eso es todo.
Esto funciona muy bien si configura su servidor django fcgi bajo 'upstart'. 'initctl reload
¡Finalmente encontramos la solución adecuada para esto!
http://rambleon.usebox.net/post/3279121000/how-to-gracefully-restart-django-running-fastcgi
primero envía una señal HUP flup para señalar un reinicio.Flup entonces hacer esto a todos sus hijos:
- cierra el socket que evitar que los niños inactivos
- envía una señal INT
- espera 10 segundos
- 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 se ejecuta flup paso 2
entonces su servidor morirá con KeyboardInterrupt
, dando al usuario un error 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.
Como se señaló en los comentarios en esa publicación, esto solo funciona para flup 1.0.3. Además, no pude hacer que esto funcione con prefork, solo enhebrado. – raylu
¿Existe algún problema o razón particular para no usar flup 1.0.3? Lo estoy usando con el modo prefork y funciona bien. – gingerlime
- 1. cómo servidores virtuales nginx + fcgi para django?
- 2. cómo implementar django debajo de un suburbal detrás de nginx
- 3. ¿Reiniciar nginx sin sudo?
- 4. Acceso a Django Admin sobre HTTPS detrás de Nginx
- 5. No se puede reiniciar nginx
- 6. ¿Por qué Django fcgi acaba de morir? ¿Cómo puedo averiguarlo?
- 7. Python Flask + nginx fcgi - ¿salida de respuesta grande?
- 8. Django y fcgi - pregunta de registro
- 9. Ejecutando nodejs bajo nginx
- 10. Unicornio vs Pasajero Independiente detrás de nginx
- 11. ¿Puede el calamar correr detrás de nginx?
- 12. ¿Cómo administrarías la autenticación X509 en una aplicación Django detrás de un proxy Nginx?
- 13. Cómo configurar Nginx detrás de un proxy corporativo
- 14. nginx django 502 bad gateway
- 15. Cómo ejecutar nginx + python (sin django)
- 16. Configuración para Django, Apache y Nginx
- 17. La aplicación FastCGI detrás de NGINX no puede detectar que se usa la conexión segura HTTPS
- 18. CherryPy detrás de Nginx reverse-proxy POST solicitudes corrompidas/truncadas
- 19. ¿Es necesario poner Unicorn detrás de Nginx (o Apache)
- 20. Rails 3 y FCGI?
- 21. Nginx/Django Admin POST https solo
- 22. Implementación de la aplicación Django en nGINX
- 23. PyDev y Django: ¿cómo reiniciar el servidor de desarrollo?
- 24. ¿Cómo se degrada graciosamente Rails 3 "data-method = 'delete'"?
- 25. ¿Cómo usar django-compressor detrás del equilibrador de carga?
- 26. uwsgi + django vía Nginx - uwsgi settings/spawn?
- 27. Cómo reiniciar un servidor node.js
- 28. Reiniciar una aplicación Django que se ejecuta en Apache + mod_python
- 29. ¿Cómo ejecutar múltiples sitios django en Nginx y uwsgi?
- 30. Ejecutando un sitio de Django en mod_wsgi
si pone un nuevo fcgi en un nuevo puerto, ¿no reenviaría nginx los usuarios ya registrados al nuevo proceso? sería lo mismo que reiniciar en frío el proceso fcgi – Javier
De hecho, reenviará a todos los usuarios al nuevo proceso; eso no hace daño El problema con el reinicio en frío es que el proceso en ejecución se cancela, por lo que las solicitudes HTTP * en progreso * fallan. Este es el caso en el que OP se preocupa (IIUC) –
Eso es útil. ¡Gracias! – evo