2010-12-14 12 views
20

Forse si tratta di un comportamento completamente normale, ma ritengo che la tabella django_session sia molto più grande di quanto dovrebbe essere.Tabella della sessione Django enorme, comportamento normale o bug?

Prima di tutto, ho eseguito il seguente comando pulizia giornaliera quindi la dimensione non è causato da sessioni scadute:

DELETE FROM %s WHERE expire_date < NOW() 

I numeri:

  • Abbiamo circa 5000 visitatori unici (esclusi i robot) ogni giorno.
  • Il SESSION_COOKIE_AGE è impostato sul valore predefinito, 2 settimane
  • Il tavolo ha un po 'più di 1.000.000 righe

Quindi, sto cercando di indovinare che Django genera anche le chiavi di sessione per tutti i bot che visita il sito e che i bot non memorizzano i cookie in modo che generino continuamente nuovi cookie.

Ma ... è questo comportamento normale? C'è un'impostazione in modo che Django non generi sessioni per utenti anonimi, o almeno ... nessuna sessione per utenti che non usano sessioni?

risposta

17

Dopo un po 'di debug sono riuscito a rintracciare la causa del problema. Uno dei miei middleware (e la maggior parte delle mie opinioni) ha uno request.user.is_authenticated() in loro.

Il django.contrib.auth middleware imposta request.user-LazyUser()

Fonte: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/middleware.py?rev=14919#L13 (non vedo il motivo per cui v'è una return None lì, ma ok ...)

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 

I LazyUser chiamate get_user(request) per ottenere l'utente:

Fonte: 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 

Il metodo get_user(request) fa un user_id = request.session[SESSION_KEY]

Fonte: 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 

Al momento l'accesso alla sessione imposta accessed true:

Fonte: 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 

E che causa la sessione per inizializzare. Il bug è stato causato da un backend di sessione difettoso che genera anche una sessione quando accessed è impostato su true ...

+0

So che questa risposta è stata scritta molto tempo fa, ma vedo lo stesso problema. La spiegazione sembra avere senso, ma c'è una soluzione? Grazie! – alan

+0

Per me la soluzione era assicurarsi che le sessioni non venissero generate quando gli articoli non erano realmente usati. Uno dei miei middleware imposta la sessione su 'accessible' in tutti i casi provocandone la generazione su ogni visualizzazione di pagina per ogni bot. – Wolph

+0

Hmm ... deve essere un problema diverso dal mio allora. Ho provato a creare una nuovissima app django 1.4 e django.contrib.auth.views.login sembra far sì che una nuova sessione venga salvata se l'utente è anonimo e non ha visitato in precedenza. Ho creato una nuova domanda per questo: http://stackoverflow.com/questions/17098142/django-session-created-in-database-when-login-page-loaded. Sarebbe bello se potessi dare un'occhiata. Grazie! – alan

-3

Django offre un management command to cleanup sessioni scadute!

+1

Come ho detto nella mia domanda iniziale, non sto parlando di sessioni scadute. Eseguo già un comando di pulizia giornaliero (non la versione di Django poiché quella muore molto prima di raggiungere questa quantità di sessioni). – Wolph

3

È possibile per i robot accedere a qualsiasi pagina in cui si imposta qualcosa in una sessione utente (anche per utenti anonimi) o qualsiasi pagina in cui si utilizza session.set_test_cookie() (ad esempio la vista di accesso predefinita di Django in chiamate a questo metodo)? In entrambi questi casi viene creato un nuovo oggetto di sessione. Escludere tali URL in robots.txt dovrebbe aiutare.

+0

Il problema era che in uno dei middleware stavo usando le sessioni per rilevare se alcuni cookie dovevano essere impostati. Grazie per avermi indicato nella giusta direzione :) +1 – Wolph

0

Per il mio caso, ho impostato erroneamente SESSION_SAVE_EVERY_REQUEST = True in settings.py senza comprendere il significato esatto.

Quindi ogni richiesta al mio servizio django generava una voce di sessione, in particolare la richiesta di test di heartbeat da parte dei bilanciatori di carico a monte. Dopo diversi giorni di funzionamento, il tavolo django_session si è trasformato in un enorme tavolo.

Problemi correlati