Django / Memcached错误:在请求完成之前删除了请求的会话

时间:2017-02-13 18:33:39

标签: django memcached python-memcached

以下是完整错误:请求的会话在请求完成之前被删除。例如,用户可能已在并发请求中注销。

我在使用我的缓存的会话中使用python-memcached。每隔几天我就会收到其中一个错误。它由request.session.save()上的UpdateError引发。它来自sessions / middleware.py中的第60行。 99%的时间一切正常。我在GET和POST请求的许多不同URL上看到了这个错误。用户报告他们没有单击注销按钮。他们还报告说这是在登录后5分钟发生的,所以他们的会话没有到期。我已经运行了超过一个月的缓存中有0次驱逐。如果我谷歌这个错误,看起来没有人曾经有过这个错误。

我认为与memcached的连接可能因某些原因而关闭。它在localhost上运行。我唯一看到这个错误的时候是将我的缓存配置设置为运行memcached但没有在该界面上监听的服务器。这会在每个请求上生成这个确切的异常。那么memcache是​​否有某种方式拒绝侦听第二次或第二次连接或丢弃连接?

以下是我的设置:

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': '127.0.0.1:11211',
        'TIMEOUT': 1209600,  # Two weeks
    },
}

SESSION_SAVE_EVERY_REQUEST = True
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_COOKIE_SECURE = CSRF_COOKIE_SECURE = True
SESSION_COOKIE_AGE = 60 * 90  # In 90 minutes

导致此错误的可靠方法似乎是在请求运行时在shell中运行带有会话密钥的cache.delete。所以有些东西正在删除缓存键。我不知道它的Django还是Memcached。 Memcached确实说STAT evictions 0

3 个答案:

答案 0 :(得分:0)

我制作了这个中间件来解决这个问题。它似乎已经照顾好了。另请检查文件描述符限制。

class SLSessionMiddleware(SessionMiddleware):
    """
    Fixes a bug where sessions sometime fail to be set. Catches the error 10 times and gives up.
    """

    def process_response(self, request, response):

        last_exception = None
        for i in range(10):
            try:
                return super().process_response(request, response)
            except Exception as e:
                request.session.cycle_key()
                time.sleep(1)
                last_exception = e

        raise last_exception

答案 1 :(得分:0)

当我启用Django的DummyCache来防止在开发过程中缓存视图时,我也遇到了这个错误(请注意,我将Redis用作缓存后端)。

在尝试访问您网站的管理员时,请确保禁用DummyCache。

Django文档提供了有关为什么看到错误的提示:

  

最后,Django附带了一个“虚拟”缓存,该缓存实际上并没有缓存-它只是实现了缓存接口而无所事事。

我根据自己的工作在settings.py文件的这两行之间进行选择。

"BACKEND": 'django.core.cache.backends.dummy.DummyCache' if DEBUG else "django_redis.cache.RedisCache",
"BACKEND": "django_redis.cache.RedisCache",

答案 2 :(得分:0)

在我的情况下,我使用SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'

从备份中更新数据(loaddata左右)时,我在下次访问时看到此错误。

因此,与此类操作一起,有必要删除缓存中的相应条目: cache.del('django.contrib.sessions.cached_dbo27db603b30jabewi7zkwd78b05zq0vf')。 (当然,也可以从redis客户端中删除。)