以下是完整错误:请求的会话在请求完成之前被删除。例如,用户可能已在并发请求中注销。
我正在使用python memcached和使用缓存的会话。每隔几天我就会犯这样的错误。它是由request.session.save()上的UpdateError抛出的。它来自sessions/middleware.py中的第60行。99%的时间一切正常。我在GET和POST请求的许多不同URL中都看到过这个错误。用户报告他们没有单击注销按钮。他们还报告说,这种情况发生在登录后5分钟,因此他们的会话不会过期。我的缓存中有0个驱逐,它已经运行了一个多月。如果我用谷歌搜索这个错误,看起来以前从来没有人得到过。
我认为与memcached的连接可能由于某种原因而关闭。它在本地主机上运行。我唯一一次看到这个错误是在我将缓存配置设置为运行memcached的服务器时,但该服务器没有在该接口上侦听。这将在每个请求中生成这个确切的异常。那么,内存缓存有没有可能在一两秒钟内拒绝侦听或断开连接呢?
以下是我的设置:
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
。
我制作了这个中间件来解决这个问题。它似乎已经处理好了。还要检查你的文件描述符限制。
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
当我启用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",
在我的情况下,我使用SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'
。
当我从备份中续订数据(加载数据左右)时,我在下次访问时会看到这个错误。
因此,连同这样的操作一起,有必要删除缓存中的相应条目:cache.del('django.contrib.sessions.cached_dbo27db603b30jabewi7zkwd78b05zq0vf')
。(当然,你也可以从redis客户端删除。)