我完全糊涂了。几天前,我的 Django 应用开始运行速度明显变慢。
原来是下面的Django视图需要
def speed_test(request):
start = time.time() # measuring execution time
b = request.user.is_authenticated # THIS somehow creates a problem
response = {"test": "test"} # constructing a dummy response
end = time.time()
logger.warning("speed test: " + str(end - start) + " auth = " + str(b)) # logging
return HttpResponse(json.dumps(response))
17/Apr/2021 17:18:18 WARNING speed test: 8.06065821647644 auth = True
17/Apr/2021 17:23:04 WARNING speed test: 6.508827209472656e-05 auth = False
is_authenticated
可以被 AbstractBaseUser
中的任何函数替换,结果相同。
如果我删除对 is_authenticated
的调用,对于每个用户来说一切都会很快。
使用runserver
和gunicorn
/uwsgi
复制它。
但我无法在我的开发笔记本电脑上重现它,即使连接到同一个远程数据库。所以看起来不像是数据库问题,也绝对不是网络问题。
Django 3.08、python 3.8、ubuntu。尝试制作全新的 venv - 无济于事。
数据库连接尽可能默认:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'user',
'USER': 'user',
'PASSWORD': 'password',
'HOST': 'hostname',
'PORT': '5432',
}
}
如果您能提供有关如何解决此问题的任何提示,我将不胜感激。
答案 0 :(得分:1)
Django 延迟加载 request.user 以便根据身份验证状态它可以是 User 或 AnonymousUser 。它仅在访问属性时“唤醒”并返回适当的类。在这种情况下,我们正在调用 is_authenticated
属性,现在它必须调用数据库进行检查。在您的情况下,对 db 的查询很可能需要很长时间。
答案 1 :(得分:1)
request.user
是一个惰性属性。这意味着 Django 将不获取登录的用户对象,除非你真的需要它。
如果您因此使用 request.user.is_authenticated
,那么这将需要对数据库进行查询以获取用户对象。如果没有与登录用户的会话,那么检索 request.user
会很快,因为它甚至不会查询数据库:如果会话 ID 的会话数据丢失,它将简单地返回 { {1}} 个对象。
如果这是系统进行的第一个查询,情况会更糟,因为那时没有打开的连接,因此可能需要额外的逻辑来首先连接到数据库。尤其是众所周知,PostgreSQL 在打开连接方面非常昂贵。
Django 通常会使用一个连接池的开放连接,并为新查询重用连接。但如果这是第一次查询,则池通常是空的,因此打开连接并进行查询需要一些努力。