如何防止运行时错误(“无法创建新的会话密钥。”)?

问题描述 投票:0回答:7

客户的 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 的缓存后端的更高版本已经添加了一个重试循环,这应该可以避免这种间歇性的失败,代价是请求偶尔会多花几秒钟。

django amazon-ec2 memcached
7个回答
6
投票

刚刚解决了与

apt-get install memcached
相同的问题。可能也是你的情况。

Ou,对不起,这不是你的情况。我刚刚更仔细地阅读了问题。但我会留下我的答案——因为这是关于这个运行时错误的。


3
投票

查看启动板上的 python-memcached 代码,您应该能够调整

dead_retry
retry_timeout
。另一种选择可能是在一个或两个应用程序服务器上运行低内存、低连接的 memcached 实例,作为无法访问主 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'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.")
  • you can monkey-patch
    django.contrib.sessions.backends.base.SessionBase._get_new_session_key
    to do a
    time.sleep(0.001)
    .
  • 你也可以检查你的熵

这是命令:

cat /proc/sys/kernel/random/entropy_avail

2
投票

在 memcache 配置文件中(e.g.

/etc/sysconfig/memcached
/etc/memcached.conf
),您可能需要更改:

-l 127.0.0.1

-l 0.0.0.0

允许 Web 服务器连接到内存缓存服务器(如果它们在不同的主机上)。


1
投票

我在运行 Django 项目的本地开发版本时遇到此错误,因为它定期无法连接到非本地缓存。我意识到我可以将我的会话后端更改为基于文件的会话来解决这个问题。

在 Django 这个本地开发版本的设置文件中,我简单地设置了以下值:

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

这不是我会在生产环境中使用的解决方案,也不是我向原始发布者建议的解决方案,但我花了几分钟才弄清楚问题出在哪里,这是出现的唯一结果之一当我用谷歌搜索时,所以我想我可能会在这里发帖来帮助其他有类似问题的人。


-1
投票

我遇到了同样的问题,检查在 django 和 memcached 中配置的端口。可能两者不同。

您可以更改 memcached 端口 vim /etc/memcached.conf 找到 'Default connection port is' 根据您的需要更改重新启动 memcached 服务


-1
投票

这就是CPU短缺。当请求完成时,观看 /var/log/apache/error.log 可能是监控的最佳位置。当您使用 Web 控制台时,还可以使用 htop tp 监控您的 CPU。 你应该增加 CPU 核心

© www.soinside.com 2019 - 2024. All rights reserved.