2010-12-14 16 views
20

Być może jest to normalne zachowanie, ale mam wrażenie, że stół django_session jest znacznie większy niż powinien.Ogromna tabela sesji Django, normalne zachowanie lub błąd?

Przede wszystkim, należy uruchomić następujące polecenie czyszczenia codziennie więc rozmiar nie jest spowodowane przeterminowanych sesji:

DELETE FROM %s WHERE expire_date < NOW() 

Numery:

  • Mamy około 5000 unikalnych odwiedzających (z wyłączeniem botów) każdego dnia.
  • SESSION_COOKIE_AGE jest ustawiony domyślnie, 2 tygodnie
  • Tabela ma trochę ponad 1.000.000 wierszy

Więc zgaduję, że Django generuje także klucze sesji dla wszystkich botów, które odwiedza strony i że boty nie przechowują plików cookie, aby stale generować nowe pliki cookie.

Ale ... czy to normalne zachowanie? Czy istnieje ustawienie, aby Django nie generował sesji dla anonimowych użytkowników lub przynajmniej ... sesji dla użytkowników, którzy nie korzystają z sesji?

Odpowiedz

17

Po krótkim debugowaniu udało mi się prześledzić przyczynę problemu. Jeden z moich middleware (i większość moich widoków) ma w nich request.user.is_authenticated().

django.contrib.auth middleware ustawia request.user do LazyUser()

Źródło: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/middleware.py?rev=14919#L13 (nie wiem dlaczego tam jest return None tam, ale 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 

W LazyUser rozmowy get_user(request) dostać użytkownika:

Źródło: 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 

Sposób get_user(request) robi user_id = request.session[SESSION_KEY]

Źródło: 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 

Po dostępu sesji ustawia accessed true:

Źródło: 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 

A to powoduje, że sesja zainicjować. Błąd został spowodowany przez wadliwe backend sesji, który generuje również sesję, gdy accessed jest ustawiona na true ...

+0

Wiem, że ta odpowiedź została napisana dawno temu, ale widzę ten sam problem. Wydaje się, że wyjaśnienie ma sens, ale czy jest jakieś rozwiązanie? Dzięki! – alan

+0

Dla mnie poprawka polegała na upewnieniu się, że sesje nie zostały wygenerowane, gdy nie są naprawdę używane. Jedno z moich middleware ustawia sesję na "access" we wszystkich przypadkach, powodując jej wygenerowanie na każdym odsłony strony dla każdego bota. – Wolph

+0

Hmm ... to musi być inny problem niż mój. Próbowałem stworzyć zupełnie nową aplikację django 1.4, a django.contrib.auth.views.login wydaje się powodować zapisanie nowej sesji, jeśli użytkownik jest anonimowy i nie odwiedził wcześniej. Stworzyłem nowe pytanie: http://stackoverflow.com/questions/17098142/django-session-created-in-database-when-login-page-loaded. Byłoby wspaniale, gdybyś mógł rzucić okiem. dzięki! – alan

-3

Django oferuje management command to cleanup tych wygasłych sesji!

+1

Jak już powiedziałem w swoim pierwotnym pytaniu, nie mówię o sesjach, które wygasły. Uruchomiłem już codzienne polecenie czyszczenia (nie wersję Django, ponieważ umiera na długo przed osiągnięciem tej liczby sesji). – Wolph

3

Czy roboty mogą uzyskać dostęp do strony, na której ustawiono coś w sesji użytkownika (nawet dla anonimowych użytkowników), lub jakiejkolwiek strony, na której używany jest session.set_test_cookie() (na przykład domyślny widok logowania Django w wywołaniach tej metody)? W obu przypadkach tworzony jest nowy obiekt sesji. Wyłączenie takich adresów URL w pliku robots.txt powinno pomóc.

+0

Problem polegał na tym, że w jednym z programów pośrednich używałem sesji do wykrycia, czy jakiś plik cookie musiał zostać ustawiony. Dzięki za wskazanie mi w dobrym kierunku :) +1 – Wolph

0

W moim przypadku, błędnie ustawić SESSION_SAVE_EVERY_REQUEST = True w settings.py bez zrozumienia dokładnego znaczenia.

Następnie każde żądanie do mojej usługi django generuje wpis sesji, w szczególności żądanie testu pulsu od nadrzędnych mechanizmów równoważenia obciążenia. Po kilkudniowych biegach stół django_session okazał się ogromny.

Powiązane problemy