Подтвердить что ты не робот

Как предотвратить RuntimeError ( "Невозможно создать новый ключ сеанса" )?

Клиентское приложение Django прерывается (примерно два раза в день), бросая RuntimeError("Unable to create a new session key."):

    Traceback (most recent call last):
  File "/usr/local/lib/python2.6/dist-packages/django/core/handlers/base.py", line 111, in get_response
    response = callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python2.6/dist-packages/django/contrib/admin/views/decorators.py", line 17, in _checklogin
    if request.user.is_active and request.user.is_staff:
  File "/usr/local/lib/python2.6/dist-packages/django/contrib/auth/middleware.py", line 9, in __get__
    request._cached_user = get_user(request)
  File "/usr/local/lib/python2.6/dist-packages/django/contrib/auth/__init__.py", line 107, in get_user
    user_id = request.session[SESSION_KEY]
  File "/usr/local/lib/python2.6/dist-packages/django/contrib/sessions/backends/base.py", line 47, in __getitem__
    return self._session[key]
  File "/usr/local/lib/python2.6/dist-packages/django/contrib/sessions/backends/base.py", line 195, in _get_session
    self._session_cache = self.load()
  File "/usr/local/lib/python2.6/dist-packages/django/contrib/sessions/backends/cache.py", line 16, in load
    self.create()
  File "/usr/local/lib/python2.6/dist-packages/django/contrib/sessions/backends/cache.py", line 33, in create
    raise RuntimeError("Unable to create a new session key.")
RuntimeError: Unable to create a new session key.

Как вы можете видеть из трассировки, это происходит глубоко в недрах django.contrib.sessions при использовании бэкэнда сеанса кэша с бэкэном кэша memcached.

Билет в Django trac (https://code.djangoproject.com/ticket/14093) предлагает изменить хэш-код сеанса от MD5 до UUID4, но это не поможет - проблема это сеть. Я наблюдал (с tcpdump), что это исключение может возникнуть, когда TCP-соединение с сервера приложений на сервере memcache истекает из-за потери пакетов.

У нас есть два сервера приложений и один сервер memcached (1.4.2), все из которых работают в Amazon EC2. В периоды высокого спроса я наблюдал, как один сервер приложений обменивался 75 000 пакетов в секунду с сервером memcache. В течение этого периода высокого спроса я заметил, что один пакет SYN для нового соединения memcache теряется, что приводит к таймауту соединения python-memcache (до того, как у ядра даже было изменение для повторной передачи) и RuntimeError.

Я не понимаю, как это решить. Я бы хотел настроить таймер повторной передачи Linux TCP менее трех секунд, но он не настраивается. В противном случае я хотел бы, чтобы python-memcache повторил соединение пару раз, прежде чем сдаваться, но это не будет. Я вижу, что pylibmc имеет настраиваемое поведение соединения и повтора, но мне не удалось найти комбинацию параметров, которые работают с потерей пакетов.

Идеи?

4b9b3361

Ответ 1

Посмотрев на код python-memcached на панели запуска, вы сможете настроить dead_retry и retry_timeout. Другим вариантом может быть запуск низкоуровневого экземпляра memcached с низким объемом памяти на одном или обоих серверах приложений в качестве резервной копии, когда основной сервер memcached недостижим.

Ответ 2

Просто решить ту же проблему с apt-get install memcached. Возможно, это и ваше дело.

О, извините, это не ваше дело. Я просто прочитал вопрос с большим вниманием. Но я оставлю свой ответ, потому что это связано с этой ошибкой времени выполнения.

Ответ 3

https://github.com/django/django/blob/master/django/contrib/sessions/backends/cache.py

def create(self):
    # Because a cache can fail silently (e.g. memcache), we don't know if
    # we are failing to create a new session because of a key collision or
    # because the cache is missing. So we try for a (large) number of times
    # and then raise an exception. That the risk you shoulder if using
    # cache backing.
    for i in xrange(10000):
        self._session_key = self._get_new_session_key()
        try:
            self.save(must_create=True)
        except CreateError:
            continue
        self.modified = True
        return
    raise RuntimeError("Unable to create a new session key.")
  • вы можете обезьян-патч django.contrib.sessions.backends.base.SessionBase._get_new_session_key выполнить time.sleep(0.001).
  • вы также можете проверить свою энтропию:

здесь команда:

cat /proc/sys/kernel/random/entropy_avail

Ответ 4

Я получал эту ошибку при запуске локальной версии разработки проекта Django, потому что периодически возникала проблема с подключением к нелокальному кешу. я реализовано, что я могу изменить свою сессионную базу на сеанс на основе файлов для решения проблемы.

В файле настроек этой локальной версии разработки Django я просто устанавливаю следующее значение:

SESSION_ENGINE = 'django.contrib.sessions.backends.file'

Это не решение, которое я бы использовал в производственной среде, а не решение, которое я предложил бы оригинальному плакату, но мне потребовалось несколько минут, чтобы выяснить, в чем проблема, и это один из единственных результатов который появился, когда я Googled, так что я решил, что я мог бы разместить здесь, чтобы помочь другим с подобной проблемой.

Ответ 5

Такая же проблема, с которой я столкнулся, проверяет порты, настроенные в django и memcached. Возможно, оба они разные.

вы можете изменить порт memcached vim/etc/memcached.conf найти "Порт подключения по умолчанию" изменен в соответствии с вашей необходимостью перезапустить службы memcached

Ответ 6

В файл /etc/sysconfig/memcached внесены изменения

-l 127.0.0.1 - -l 0.0.0.0

на некоторых машинах это в файле /etc/memcached.conf