【问题标题】:Django / Memcached error: The request's session was deleted before the request completedDjango / Memcached 错误:请求的会话在请求完成之前被删除
【发布时间】:2017-02-13 18:33:38
【问题描述】:

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

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

我认为与 memcached 的连接可能由于某种原因而关闭。它在本地主机上运行。我看到此错误的唯一一次是当我将缓存配置设置为运行 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

【问题讨论】:

  • 我遇到了同样的问题 - 现在互联网上似乎正好有三个人遇到了这个问题。 ;) 可能是四个。
  • @Teekin 我不明白了。我要检查的事情是升级 memcached、memcached 的文件描述符和您的 Web 服务器,以及每个运行的用户。使 memcahed 通过本地套接字运行。并添加我在下面粘贴的中间件。
  • 我最近注意到产生此错误的视图主要由 ajax 脚本调用或它们处理文件(例如返回图像)。就我而言,用户肯定有可能在并发请求中注销 - 我只是想一直防止出现此错误消息。
  • 然后在你的设置文件中给它一个空处理器。
  • 在我刚刚调用 set_autocommit(False)、commit() 等之后,我得到了这个错误。我扭转了一切。但没有成功解决。奇怪的问题。

标签: django memcached python-memcached


【解决方案1】:

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

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

【讨论】:

  • 这似乎是一个非常老套的解决方案。它对 Daniel K. 不起作用并不令我感到惊讶,因为它可能对环境做出了很多假设。
  • @Teekin 哦,是的,它非常非常hacky。我一点也不为此感到骄傲。这是我在花了几个小时但一无所获之后想出的。这是一个非常间歇性的问题,几乎不可能重现,因此很难诊断。
【解决方案2】:

当我启用 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",

【讨论】:

    【解决方案3】:

    就我而言,我使用SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-18
      • 1970-01-01
      • 1970-01-01
      • 2017-12-04
      • 1970-01-01
      相关资源
      最近更新 更多