Python 请求';在请求完成之前,已删除的会话。例如,用户可能已在并发请求中注销

Python 请求';在请求完成之前,已删除的会话。例如,用户可能已在并发请求中注销,python,django,Python,Django,我有一个Python/Django应用程序,有时会有100多个用户登录。有一天,我在Django错误日志中发现: The request's session was deleted before the request completed. The user may have logged out in a concurrent request, for example. 虽然这封信是用很容易理解的英语写的,但我不知道 到底发生了什么 为什么会这样 我是否需要担心它 如果是,我如何防止这种

我有一个Python/Django应用程序,有时会有100多个用户登录。有一天,我在Django错误日志中发现:

The request's session was deleted before the request completed. 
The user may have logged out in a concurrent request, for example.
虽然这封信是用很容易理解的英语写的,但我不知道

  • 到底发生了什么
  • 为什么会这样
  • 我是否需要担心它
  • 如果是,我如何防止这种情况再次发生
我发现了一个标题几乎相同的问题,但不同的是,我没有任何关于缓存的设置

如果您需要任何代码,请在评论中告诉我


谢谢你的时间

实际发生的情况:当同一用户使用相同的会话密钥发出请求时,用户的会话被破坏(即他们注销或会话过期)

发生原因:例如,如果用户打开了两个选项卡,并在其中一个选项卡中注销,而另一个选项卡也发出了请求,则可能会发生这种情况。如果这两种情况都很快相继发生,那么其中一个就会出现这个错误


你需要担心吗?:除非你在日志中看到很多这样的事件,否则就不需要担心了,在这种情况下,会出现一些错误。如果只发现一次错误,则无需担心。

如果用户在“非活动”状态下尝试登录,也会发生此错误。

如果运行django服务器的服务器用户(如果由不同于root的用户运行)没有足够的目录权限,则会发生此问题。 因此,服务器只有读取权限,而没有写入权限。 可以使用linux命令编辑项目目录的权限:

chmod u=rwx,g=rx,o= /project_path
其中u表示用户,g表示用户组,o表示其他用户

您可以使用ls的-d选项检查目录的权限,如下所示:

ls -lhd /
ls -lhd /etc
ls -lhd /etc/opt
ls -lhd /etc/opt/$DJANGO_PROJECT

如果用户可能在并发请求中注销,也可能发生此错误

这也可能发生,因为您将会话存储在虚拟缓存后端

例如:

如果您已将“
DummyCache
”配置为默认缓存系统,或者如果您的
SESSION\u Cache\u ALIAS
指向虚拟缓存,则即使在请求-响应周期之间,这些SESSION数据也有可能被删除。也就是说,您的请求已到达Djagno服务器,并且正在积极处理中

问题

您的
设置
似乎处于任何可能的配置中

案例A:

# Possible Current Configuration 
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
        'LOCATION': 'unique-snowflake',
     }
}

SESSION_ENGINE = "django.contrib.sessions.backends.cache"

解决方案

我希望,现在您找到了解决方案,如果会话引擎依赖于缓存,最好不要将它们指向
DummyCache

您可以将
会话_引擎
与缓存一起使用,并与任何其他缓存协同使用

SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "default"  # or comfortabley anything else
CACHES = {
    'default': {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/1",
        "OPTIONS": {
              "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
     }
}
(Redis是我的首选配置;您可以使用
django.core.cache.backends.locmem.LocMemCache
django.core.cache.backends.memcached.MemcachedCache
或任何其他选项。 或者,如果您仍然想使用
DummyCache
,您甚至可以将会话引擎从缓存更改为类似以下内容:

# File Based
SESSION_ENGINE = "django.contrib.sessions.backends.file"

# Works In Combination With  Current Cache and Database, fairly persistant
SESSION_ENGINE = "django.contrib.sessions.backends.cached_db"   

# Cookie Based, Browser Clearing Will lose it. 
SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies"  

我得到这个错误的原因也不尽相同:由于另一个问题,数据库处于只读模式。

在我的例子中,原来是由两个数据库服务器之间的复制延迟引起的(在主[RW]-从[RO]模式下)因为我将一些请求路由到从属服务器,以便在DBs之间执行负载分配。同样的事情发生在使用2台Redis服务器作为缓存引擎时,因为它们之间的复制延迟


我们修复了将会话请求强制发送到主服务器的问题。

这个错误让我忙了几个小时,直到最后我发现我的数据库被锁定,因为我没有保存对它所做的更改。保存数据解决了这个问题。

如果您调用

request.session.clear()
当on会话存在时(因为它未被使用或超时)

只有在会话处于使用状态时,才能通过检查和清除会话来解决此问题:

if request.session:
    request.session.clear()

我怎样才能避免在日志中出现这个错误?如何捕捉它,有时我会收到django的电子邮件,说……我想这在一个月内发生了两次
if request.session:
    request.session.clear()