tutorial template examples english documentacion docs python django exception fastcgi lighttpd

python - template - Django+FastCGI-elevando aleatoriamente OperationalError



docs django project (12)

Estoy ejecutando una aplicación de Django. Lo tenía en Apache + mod_python antes, y todo estaba bien. Cambiado a Lighttpd + FastCGI. Ahora recibo al azar la siguiente excepción (ni el lugar ni la hora en que aparece parecen predecibles). Como es aleatorio, y aparece solo después de cambiar a FastCGI, supongo que tiene algo que ver con algunas configuraciones.

Se encontraron algunos resultados al buscar en Google, pero parecen estar relacionados con la configuración de maxrequests = 1. Sin embargo, utilizo el valor predeterminado, que es 0.

¿Alguna idea de dónde buscar?

PD. Estoy usando PostgreSQL. Podría estar relacionado con eso también, ya que la excepción aparece cuando se hace una consulta a la base de datos.

File "/usr/lib/python2.6/site-packages/django/core/handlers/base.py", line 86, in get_response response = callback(request, *callback_args, **callback_kwargs) File "/usr/lib/python2.6/site-packages/django/contrib/admin/sites.py", line 140, in root if not self.has_permission(request): File "/usr/lib/python2.6/site-packages/django/contrib/admin/sites.py", line 99, in has_permission return request.user.is_authenticated() and request.user.is_staff File "/usr/lib/python2.6/site-packages/django/contrib/auth/middleware.py", line 5, in __get__ request._cached_user = get_user(request) File "/usr/lib/python2.6/site-packages/django/contrib/auth/__init__.py", line 83, in get_user user_id = request.session[SESSION_KEY] File "/usr/lib/python2.6/site-packages/django/contrib/sessions/backends/base.py", line 46, in __getitem__ return self._session[key] File "/usr/lib/python2.6/site-packages/django/contrib/sessions/backends/base.py", line 172, in _get_session self._session_cache = self.load() File "/usr/lib/python2.6/site-packages/django/contrib/sessions/backends/db.py", line 16, in load expire_date__gt=datetime.datetime.now() File "/usr/lib/python2.6/site-packages/django/db/models/manager.py", line 93, in get return self.get_query_set().get(*args, **kwargs) File "/usr/lib/python2.6/site-packages/django/db/models/query.py", line 304, in get num = len(clone) File "/usr/lib/python2.6/site-packages/django/db/models/query.py", line 160, in __len__ self._result_cache = list(self.iterator()) File "/usr/lib/python2.6/site-packages/django/db/models/query.py", line 275, in iterator for row in self.query.results_iter(): File "/usr/lib/python2.6/site-packages/django/db/models/sql/query.py", line 206, in results_iter for rows in self.execute_sql(MULTI): File "/usr/lib/python2.6/site-packages/django/db/models/sql/query.py", line 1734, in execute_sql cursor.execute(sql, params) OperationalError: server closed the connection unexpectedly This probably means the server terminated abnormally before or while processing the request.


En el cambio, ¿cambió las versiones cliente / servidor de PostgreSQL?

He visto problemas similares con php + mysql, y el culpable era una incompatibilidad entre las versiones cliente / servidor (¡aunque tenían la misma versión principal!)


Quizás la variable de entorno PYTHONPATH y PATH sea diferente para ambas configuraciones (Apache + mod_python y lighttpd + FastCGI).


Al final volví a Apache + mod_python (tenía otros errores aleatorios con fcgi, además de este) y ahora todo está bien y estable.

La pregunta aún permanece abierta. En caso de que alguien tenga este problema en el futuro y lo resuelva, puede registrar la solución aquí para referencia futura. :)


Solucioné un problema similar cuando utilizaba un modelo geodjango que no estaba utilizando el ORM predeterminado para una de sus funciones. Cuando agregué una línea para cerrar manualmente la conexión, el error desapareció.

http://code.djangoproject.com/ticket/9437

Todavía veo el error al azar (~ 50% de las solicitudes) cuando hago cosas con el inicio de sesión / sesión de usuario.


¿Has considerado degradar a Python 2.5.x (2.5.4 específicamente)? No creo que Django se considere maduro en Python 2.6 ya que hay algunos cambios incompatibles. Sin embargo, dudo que esto solucione tu problema.

Además, Django 1.0.2 solucionó algunos pequeños errores nefastos, así que asegúrate de ejecutarlos. Esto muy bien podría solucionar tu problema.


Pasé por el mismo problema recientemente (lighttpd, fastcgi y postgre). Busqué una solución por días sin éxito, y como último recurso cambié a mysql. El problema se ha ido.


¿Por qué no almacenar la sesión en el caché? Conjunto

SESSION_ENGINE = "django.contrib.sessions.backends.cache"

También puedes probar el uso de postgres con pgbouncer (postgres - servidor prefork y no te gustan muchas conexiones / desconexiones por vez), pero primero revisa tu postgresql.log.

Otra versión: tiene muchos registros en las tablas de sesión y la limpieza de django-admin.py puede ayudar.


El problema podría ser principalmente con Importaciones. Al menos eso es lo que me sucedió. Escribí mi propia solución después de no encontrar nada de la web. Por favor revisa mi blog aquí: Simple Python Utility para verificar todas las Importaciones en tu proyecto

Por supuesto, esto solo le ayudará a llegar a la solución del problema original con bastante rapidez y no a la solución real para su problema en sí mismo.


Cambiar de method = prefork a method = threaded resolvió el problema para mí.


Posible solución: http://groups.google.com/group/django-users/browse_thread/thread/2c7421cdb9b99e48

Hasta hace poco tenía curiosidad por probar esto en Django 1.1.1. Esta excepción se lanzará de nuevo ... sorpresa, allí estaba de nuevo. Me llevó algo de tiempo depurar esto, la sugerencia útil fue que solo se muestra cuando se bifurca (pre). Entonces, para aquellos que reciben esas excepciones al azar, puedo decir ... arreglen su código :) De acuerdo ... en serio, siempre hay pocas maneras de hacerlo, así que primero déjenme explicar dónde está el problema primero. Si accede a la base de datos cuando cualquiera de sus módulos se importará, por ejemplo, leyendo la configuración de la base de datos, obtendrá este error. Cuando se inicia la aplicación fastcgi-prefork, primero importa todos los módulos y solo después de esto se abren los elementos secundarios. Si ha establecido una conexión db durante la importación, todos los procesos secundarios tendrán una copia exacta de ese objeto. Esta conexión se cierra al final de la fase de solicitud (señal request_finished). Entonces, el primer hijo que será llamado para procesar su solicitud, cerrará esta conexión. Pero, ¿qué pasará con el resto de los procesos secundarios? Ellos creerán que tienen una conexión abierta y presumiblemente funcional con el DB, por lo que cualquier operación de DB causará una excepción. ¿Por qué esto no se muestra en el modelo de ejecución con subprocesos? Supongo que porque los subprocesos usan el mismo objeto y saben cuándo hay algún otro subproceso que cierre la conexión. ¿Cómo arreglar esto? La mejor manera es arreglar tu código ... pero a veces puede ser difícil. Otra opción, en mi opinión bastante limpia, es escribir en algún lugar de tu aplicación un pequeño fragmento de código:

from django.db import connection from django.core import signals def close_connection(**kwargs): connection.close() signals.request_started.connect(close_connection)

Pensamiento no ideal, conectarse dos veces a la base de datos es una solución en el mejor de los casos.

Posible solución: utilizando la agrupación de conexiones (pgpool, pgbouncer), para que tenga conexiones de bases de datos reunidas y estables, y entregadas rápidamente a sus daemons FCGI.

El problema es que esto desencadena otro error, psycopg2 provocando un error InterfaceError porque está intentando desconectarse dos veces (pgbouncer ya manejó esto).

Ahora el culpable es Django signal request_finished, que desencadena connection.close () y falla de alto volumen, incluso si ya se ha desconectado. No creo que este comportamiento sea deseado, ya que si la solicitud ya ha finalizado, ya no nos importa la conexión de DB. Un parche para corregir esto debería ser simple.

El rastreo relevante:

/usr/local/lib/python2.6/dist-packages/Django-1.1.1-py2.6.egg/django/core/handlers/wsgi.py in __call__(self=<django.core.handlers.wsgi.WSGIHandler object at 0x24fb210>, environ={''AUTH_TYPE'': ''Basic'', ''DOCUMENT_ROOT'': ''/storage/test'', ''GATEWAY_INTERFACE'': ''CGI/1.1'', ''HTTPS'': ''off'', ''HTTP_ACCEPT'': ''application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5'', ''HTTP_ACCEPT_ENCODING'': ''gzip, deflate'', ''HTTP_AUTHORIZATION'': ''Basic dGVzdGU6c3VjZXNzbw=='', ''HTTP_CONNECTION'': ''keep-alive'', ''HTTP_COOKIE'': ''__utma=175602209.1371964931.1269354495.126938948...none); sessionid=a1990f0d8d32c78a285489586c510e8c'', ''HTTP_HOST'': ''www.rede-colibri.com'', ...}, start_response=<function start_response at 0x24f87d0>) 246 response = self.apply_response_fixes(request, response) 247 finally: 248 signals.request_finished.send(sender=self.__class__) 249 250 try: global signals = <module ''django.core.signals'' from ''/usr/local/l.../Django-1.1.1-py2.6.egg/django/core/signals.pyc''>, signals.request_finished = <django.dispatch.dispatcher.Signal object at 0x1975710>, signals.request_finished.send = <bound method Signal.send of <django.dispatch.dispatcher.Signal object at 0x1975710>>, sender undefined, self = <django.core.handlers.wsgi.WSGIHandler object at 0x24fb210>, self.__class__ = <class ''django.core.handlers.wsgi.WSGIHandler''> /usr/local/lib/python2.6/dist-packages/Django-1.1.1-py2.6.egg/django/dispatch/dispatcher.py in send(self=<django.dispatch.dispatcher.Signal object at 0x1975710>, sender=<class ''django.core.handlers.wsgi.WSGIHandler''>, **named={}) 164 165 for receiver in self._live_receivers(_make_id(sender)): 166 response = receiver(signal=self, sender=sender, **named) 167 responses.append((receiver, response)) 168 return responses response undefined, receiver = <function close_connection at 0x197b050>, signal undefined, self = <django.dispatch.dispatcher.Signal object at 0x1975710>, sender = <class ''django.core.handlers.wsgi.WSGIHandler''>, named = {} /usr/local/lib/python2.6/dist-packages/Django-1.1.1-py2.6.egg/django/db/__init__.py in close_connection(**kwargs={''sender'': <class ''django.core.handlers.wsgi.WSGIHandler''>, ''signal'': <django.dispatch.dispatcher.Signal object at 0x1975710>}) 63 # when a Django request is finished. 64 def close_connection(**kwargs): 65 connection.close() 66 signals.request_finished.connect(close_connection) 67 global connection = <django.db.backends.postgresql_psycopg2.base.DatabaseWrapper object at 0x17b14c8>, connection.close = <bound method DatabaseWrapper.close of <django.d...ycopg2.base.DatabaseWrapper object at 0x17b14c8>> /usr/local/lib/python2.6/dist-packages/Django-1.1.1-py2.6.egg/django/db/backends/__init__.py in close(self=<django.db.backends.postgresql_psycopg2.base.DatabaseWrapper object at 0x17b14c8>) 74 def close(self): 75 if self.connection is not None: 76 self.connection.close() 77 self.connection = None 78 self = <django.db.backends.postgresql_psycopg2.base.DatabaseWrapper object at 0x17b14c8>, self.connection = <connection object at 0x1f80870; dsn: ''dbname=co...st=127.0.0.1 port=6432 user=postgres'', closed: 2>, self.connection.close = <built-in method close of psycopg2._psycopg.connection object at 0x1f80870>

El manejo de excepciones aquí podría agregar más indulgencia:

/usr/local/lib/python2.6/dist-packages/Django-1.1.1-py2.6.egg/django/db/__init__.py

63 # when a Django request is finished. 64 def close_connection(**kwargs): 65 connection.close() 66 signals.request_finished.connect(close_connection)

O podría manejarse mejor en psycopg2, para no lanzar errores fatales si todo lo que estamos tratando de hacer es desconectar y ya está:

/usr/local/lib/python2.6/dist-packages/Django-1.1.1-py2.6.egg/django/db/backends/__init__.py

74 def close(self): 75 if self.connection is not None: 76 self.connection.close() 77 self.connection = None

Aparte de eso, tengo pocas ideas.


Trato de dar una respuesta a esto, incluso si no estoy usando django, sino piramidales como marco. Me encontré con este problema desde hace mucho tiempo. El problema era que era realmente difícil producir este error para las pruebas ... De todos modos. Finalmente lo resolví explorando todo el contenido de las sesiones, las sesiones de alcance, instancias de sesiones, motores y conexiones, etc. Encontré esto:

http://docs.sqlalchemy.org/en/rel_0_7/core/pooling.html#disconnect-handling-pessimistic

Este enfoque simplemente agrega un oyente al grupo de conexiones del motor. En el oyente, se consulta una selección estática a la base de datos. Si falla, intente establecer una nueva conexión con la base de datos antes de que falle. Importante: esto sucede antes de que se arrojen otras cosas a la base de datos. Por lo tanto, es posible verificar previamente la conexión lo que evita que el resto del código falle.

Esta no es una solución limpia, ya que no resuelve el error en sí, pero funciona como un encanto. Espero que esto ayude a alguien.


Huele como un posible problema de enhebrado. No se garantiza que Django sea seguro para subprocesos, aunque los documentos en el archivo parecen indicar que Django / FCGI pueden ejecutarse de esa manera. Intenta correr con prefork y luego elimina la mierda del servidor. Si el problema desaparece ...