客户端的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.
从回溯中可以看到,当使用缓存会话后端和memcached缓存后端时,这种情况发生在django.contrib.sessions
的深处。
Django跟踪票证(https://code.djangoproject.com/ticket/14093)建议将会话密钥哈希值从MD5更改为uid4,但这没有帮助——问题是网络。我观察到(使用tcpdump),当从应用服务器到memcache服务器的TCP连接由于数据包丢失而超时时,可能会发生此异常。
我们有两个应用服务器和一个memcached(1.4.2)服务器,都运行在Amazon EC2上。在高需求期间,我观察到一个应用程序服务器与memcache服务器每秒交换75,000个数据包。在这段高需求期间,我观察到一个新的memcache连接的SYN包丢失了,导致python-memcache连接超时(在内核甚至有机会重新传输之前)和RuntimeError
。
我不知道如何解决这个问题。我希望将Linux的TCP重传计时器调优到3秒以下,但这是不可调的。如果做不到这一点,我想让python-memcache在放弃之前重试连接几次,但它不会。我看到pylibmc有可配置的连接和重试行为,但我还没能找到一个组合的选项,工作围绕丢包。
想法?
更新:
对于看到"无法创建新的会话键"的用户;一直以来,这只是意味着您的memcache没有正确设置。下面的一些答案讨论了要检查的事情(软件包安装了吗?
我们遇到的问题是间歇性—几千个请求中只有一个会失败。我使用tcpdump
来显示,当TCP三次握手中的三个数据包中的一个丢失时(由于网络拥塞),会发生这种情况,导致python-memcache
超时并引发异常,导致"无法创建新的会话密钥";RuntimeError
.
在云提供商网络中丢包可能是不可避免的。理想情况下,Linux内核会使TCP初始重传计时器可配置,但在我研究这个问题时,情况似乎并非如此。这意味着python-memcache
库本身需要具有某种超时-重试逻辑,而它(当时)没有。
看起来Django缓存后端的新版本增加了一个重试循环,这应该可以避免这种间歇性的失败,但代价是请求偶尔会多花几秒钟的时间。
刚刚解决了apt-get install memcached
的相同问题。也许这也是你的情况。
查看launchpad上的python-memcached代码,您应该能够调整dead_retry
和retry_timeout
。另一种选择可能是在一个或两个应用服务器上运行低内存、低连接的memcached实例,作为主memcached服务器不可达时的后备。
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's 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
我得到这个错误运行本地,开发版本的Django项目,因为它是定期有问题连接到非本地缓存。我意识到我可以将会话后端改为基于文件的会话来解决这个问题。
在Django本地开发版本的设置文件中,我简单地设置了以下值:
SESSION_ENGINE = 'django.contrib.sessions.backends.file'
这不是我在生产环境中使用的解决方案,也不是我建议原始海报的解决方案,但我花了几分钟才弄清楚问题是什么,这是我在谷歌搜索时出现的唯一结果之一,所以我想我可能会在这里发帖帮助其他人解决类似的问题。
在memcache配置文件中(例如:, /etc/sysconfig/memcached
或/etc/memcached.conf
),您可能需要更改:
-l 127.0.0.1
-l 0.0.0.0
允许web服务器连接到memcache服务器(如果它们在不同的主机上)。
我遇到过同样的问题,检查django和memcached中配置的端口。可能两者都不一样
你可以改变memcached端口vim/etc/memcached.conf找到'Default connection port is'根据你的需要重新启动memcached服务
这就是CPU短缺。当请求完成时,监视/var/log/apache/error.log可能是监视的最佳位置。当您使用web控制台时,还可以使用htop tp监控您的CPU。你应该增加CPU核数