Как предотвратить 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 имеет настраиваемое поведение соединения и повтора, но мне не удалось найти комбинацию параметров, которые работают с потерей пакетов.
Идеи?
Ответы
Ответ 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