客户的 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 trac 票证 (https://code.djangoproject.com/ticket/14093) 建议将会话密钥哈希从 MD5 更改为 UUID4,但这没有帮助——问题出在网络上。我已经观察到(使用 tcpdump)当从应用程序服务器到内存缓存服务器的 TCP 连接由于数据包丢失而超时时,可能会发生此异常。
我们有两台应用程序服务器和一台 memcached (1.4.2) 服务器,都在 Amazon EC2 中运行。在高需求期间,我观察到一个应用服务器每秒与内存缓存服务器交换 75,000 个数据包。在这段高需求期间,我观察到一个用于新内存缓存连接的 SYN 数据包丢失,导致 python-memcache 连接超时(在内核甚至没有机会重新传输之前)和
RuntimeError
.
我不知道如何解决这个问题。我想将 Linux 的 TCP 重新传输计时器调整为低于三秒,但它不可调整。如果做不到这一点,我想让 python-memcache 在放弃之前重试几次连接,但它不会。我看到 pylibmc 具有可配置的连接和重试行为,但我无法找到解决数据包丢失的选项组合。
想法?
更新:
对于一直看到“Unable to create a new session key”的人来说,这只是意味着你的内存缓存设置不正确。下面的一些答案讨论了要检查的事情(是否安装了软件包?端口是否正确?)。
我们遇到的问题是间歇性——几千个请求中只有一个会失败。我用
tcpdump
来说明当TCP三次握手中的三个数据包之一丢失时(由于网络拥塞),导致python-memcache
超时并引发异常,导致“Unable to创建一个新的会话密钥”RuntimeError
.
云提供商网络中的数据包丢失可能是不可避免的。理想情况下,Linux 内核将使 TCP 初始重传计时器可配置,但在我调查此问题时似乎并非如此。这意味着
python-memcache
库本身需要有某种超时和重试逻辑,它(当时)没有。
看起来 Django 的缓存后端的更高版本已经添加了一个重试循环,这应该可以避免这种间歇性的失败,代价是请求偶尔会多花几秒钟。
刚刚解决了与
apt-get install memcached
相同的问题。可能也是你的情况。
Ou,对不起,这不是你的情况。我刚刚更仔细地阅读了问题。但我会留下我的答案——因为这是关于这个运行时错误的。
查看启动板上的 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
to do a time.sleep(0.001)
.这是命令:
cat /proc/sys/kernel/random/entropy_avail
在 memcache 配置文件中(e.g.、
/etc/sysconfig/memcached
或 /etc/memcached.conf
),您可能需要更改:
-l 127.0.0.1
到
-l 0.0.0.0
允许 Web 服务器连接到内存缓存服务器(如果它们在不同的主机上)。
我遇到了同样的问题,检查在 django 和 memcached 中配置的端口。可能两者不同。
您可以更改 memcached 端口 vim /etc/memcached.conf 找到 'Default connection port is' 根据您的需要更改重新启动 memcached 服务
这就是CPU短缺。当请求完成时,观看 /var/log/apache/error.log 可能是监控的最佳位置。当您使用 Web 控制台时,还可以使用 htop tp 监控您的 CPU。 你应该增加 CPU 核心