2010-12-14 10 views
20

Quizás esto sea un comportamiento completamente normal, pero creo que la tabla django_session es mucho más grande de lo que debería ser.Tabla de sesión de Django enorme, comportamiento normal o error?

En primer lugar, ejecute el siguiente comando de limpieza diaria por lo que el tamaño no es causada por sesiones expiradas:

DELETE FROM %s WHERE expire_date < NOW() 

Los números:

  • Tenemos alrededor 5000 visitantes únicos (bots excluidos) todos los días.
  • El SESSION_COOKIE_AGE se establece en el valor por defecto, 2 semanas
  • la tabla tiene un poco más de 1.000.000 de filas

Por lo tanto, supongo que Django también genera claves de sesión para todos los robots que visita la sitio y que los bots no almacenan las cookies por lo que continuamente genera nuevas cookies.

Pero ... ¿es este comportamiento normal? ¿Hay alguna configuración para que Django no genere sesiones para usuarios anónimos, o al menos ... sin sesiones para usuarios que no están usando sesiones?

Respuesta

17

Después de un poco de depuración, he logrado rastrear la causa del problema. Uno de mis middlewares (y la mayoría de mis visitas) tienen un request.user.is_authenticated() en ellos.

El middleware django.contrib.auth establece request.user-LazyUser()

Fuente: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/middleware.py?rev=14919#L13 (no veo por qué hay una return None allí, pero no está mal ...)

class AuthenticationMiddleware(object): 
    def process_request(self, request): 
     assert hasattr(request, 'session'), "The Django authentication middleware requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.sessions.middleware.SessionMiddleware'." 
     request.__class__.user = LazyUser() 
     return None 

Las llamadas LazyUserget_user(request) para obtener el usuario:

Fuente: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/middleware.py?rev=14919#L5

class LazyUser(object): 
    def __get__(self, request, obj_type=None): 
     if not hasattr(request, '_cached_user'): 
      from django.contrib.auth import get_user 
      request._cached_user = get_user(request) 
     return request._cached_user 

El método get_user(request) hace un Fuente user_id = request.session[SESSION_KEY]

: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/init.py?rev=14919#L100

def get_user(request): 
    from django.contrib.auth.models import AnonymousUser 
    try: 
     user_id = request.session[SESSION_KEY] 
     backend_path = request.session[BACKEND_SESSION_KEY] 
     backend = load_backend(backend_path) 
     user = backend.get_user(user_id) or AnonymousUser() 
    except KeyError: 
     user = AnonymousUser() 
    return user 

Tras acceder a la sesión establece accessed true:

Fuente: http://code.djangoproject.com/browser/django/trunk/django/contrib/sessions/backends/base.py?rev=14919#L183

def _get_session(self, no_load=False): 
    """ 
    Lazily loads session from storage (unless "no_load" is True, when only 
    an empty dict is stored) and stores it in the current instance. 
    """ 
    self.accessed = True 
    try: 
     return self._session_cache 
    except AttributeError: 
     if self._session_key is None or no_load: 
      self._session_cache = {} 
     else: 
      self._session_cache = self.load() 
    return self._session_cache 

y que provoca la reunión se inicie. El fallo fue causado por un motor defectuoso sesión que también genera una sesión cuando accessed se establece en true ...

+0

Sé que esta respuesta fue escrita hace mucho tiempo, pero estoy viendo el mismo problema. La explicación parece tener sentido, pero ¿hay alguna solución? ¡Gracias! – alan

+0

Para mí, la solución era asegurarme de que las sesiones no se generaran cuando realmente no se usaban. Uno de mis middlewares configuró la sesión para 'acceder' en todos los casos, lo que provoca que se genere en cada vista de página para cada bot. – Wolph

+0

Hmm ... debe ser un problema diferente al mío entonces. Traté de crear una nueva aplicación django 1.4 y django.contrib.auth.views.login parece causar una nueva sesión para guardar si el usuario es anónimo y no ha visitado previamente. Creé una nueva pregunta para esto: http://stackoverflow.com/questions/17098142/django-session-created-in-database-when-login-page-loaded. Sería genial si pudieras echar un vistazo. ¡Gracias! – alan

-3

Django ofrece un management command to cleanup estas sesiones expiradas!

+1

Como he dicho en mi pregunta original, no estoy hablando de sesiones caducadas. Ya ejecuto un comando de limpieza diaria (no la versión de Django, ya que esa se muere mucho antes de llegar a esta cantidad de sesiones). – Wolph

3

¿Es posible que los robots accedan a cualquier página donde establezca algo en una sesión de usuario (incluso para usuarios anónimos) o en cualquier página donde use session.set_test_cookie() (por ejemplo, la vista de inicio de sesión predeterminada de Django en este método)? En ambos casos, se crea un nuevo objeto de sesión. Excluir tales URL en robots.txt debería ayudar.

+0

El problema fue que en uno de los middlewares estaba usando las sesiones para detectar si había que configurar alguna cookie. Gracias por señalarme en la dirección correcta :) +1 – Wolph

0

Para mi caso, me puse mal SESSION_SAVE_EVERY_REQUEST = True en settings.py sin entender el significado exacto.

Luego, cada solicitud a mi servicio django generaría una entrada de sesión, especialmente la solicitud de prueba de latido de los equilibradores de carga ascendentes. Después de varios días de funcionamiento, la tabla django_session se convirtió en una enorme.

Cuestiones relacionadas