2008-12-26 15 views
8

Estoy ejecutando una aplicación 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.Django + FastCGI - alzando aleatoriamente OperationalError

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?

PS. 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. 

Respuesta

0

Al final cambié a Apache + mod_python (estaba teniendo otros errores aleatorios con fcgi, además de este) y todo está bien y estable ahora.

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. :)

+2

Esto no resuelve el problema en sí. Solo lo esquiva. : P Puede que no sea una opción para algunas personas. – pkoch

0

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

he visto problemas similares con PHP + MySQL, y el culpable era una incompatibilidad entre las versiones de cliente/servidor (aunque tenían la misma versión principal!)

+0

No. Solo cambié Apache + mod_python a Lighttpd + FastCGI. – ibz

0

Huele como un posible problema de roscado. Django es no garantizado a prueba de hilos, 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 ...

+0

Ya estoy usando prefork. – ibz

0

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

0

He solucionado un problema similar al utilizar 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) al hacer cosas con inicio de sesión de usuario/sesiones sin embargo.

-1

¿Ha considerado la degradación 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úrese de ejecutarlos. Esto muy bien podría solucionar tu problema.

0

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

0

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

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

También puede probar con postgres uso pgbouncer (postgres - servidor prefork y no les gusta a muchos Conecta/desconecta por tiempo), pero en primer lugar comprobar su postgresql.log.

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

0

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 revise mi blog aquí: Simple Python Utility to check all Imports in your project

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

0

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

3

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

Hasta hace poco tenía curiosidad para probar esto en Django 1.1.1. ¿Esta excepción se lanzará de nuevo ... sorpresa, allí estaba de nuevo. Me tomó un poco de tiempo para depurar esto, sugerencia útil fue que solo se muestra cuando (pre) bifurcación. Así que para aquellos que conseguir al azar esas excepciones, puedo decir ... fijar su código :) Ok .. en serio, no siempre son algunas maneras de hacer esto, por lo que vamos a me explico abetos, donde es un problema primera . Si accede a la base de datos , cualquiera de sus módulos importará como, por ej. leyendo la configuración de la base de datos , entonces 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 la conexión db durante la importación, todos los procesos secundarios tendrán una copia exacta de ese objeto . Esta conexión está siendo cerrada al final de la fase de solicitud (señal de petición finalizada). Por lo tanto, 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 abierto y supuestamente trabajando conexión al db, por lo que cualquier operación db causará una excepción . ¿Por qué esto no se muestra en el modelo de ejecución roscado ? Supongo porque los hilos están utilizando el mismo objeto y saben cuando cualquier otro hilo es conexión de cierre. ¿Cómo arreglar esto? La mejor manera es corregir su código ... pero esto puede ser difícil a veces. Otra opción, en mi opinión bastante limpio, es escribir en algún lugar de su aplicación pequeño trozo 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) 

No pensamiento ideales, que conecta dos veces a la base de datos es una solución temporal en el mejor.


Posible solución: utilizar la agrupación de conexiones (pgpool, pgbouncer), por lo que han agrupado las conexiones de base de datos y estable, y entregado rápido a sus demonios fcgi.

El problema es que esto desencadena otro error, psycopg2 levantando una InterfaceError porque está tratando de desconectar dos veces (pgbouncer ya se maneja esto).

Ahora el culpable es señal de Django request_finished activación connection.close(), y en su defecto ruidoso 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> 

manejo de aquí podría añadir más indulgencia Excepción:

/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 ser manejado mejor en psycopg2, por lo que no se generan errores fatales si todo lo que estamos tratando de hacer es DISCONN ect 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, no tengo muchas ideas.

0

Intento dar una respuesta a esto incluso si no estoy usando django sino piramida 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. Por último Lo resuelto por la excavación a través de todo el material de las sesiones, sesiones de ámbito, los casos de las sesiones, los motores y las conexiones etc. encontré esto:

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

Este enfoque simplemente añade un oyente a la agrupación de conexiones de la 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 cualquier otra cosa se arroje 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.

Esto 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.

Cuestiones relacionadas