在我的应用程序中,我使用了 flask-security 添加身份验证和授权主题。 SQLAlchemy 也用作数据提供者(以 MySQL 作为后端)。该应用程序运行良好。
然后,我做了一些 MySQL 跟踪,日志显示在应用程序上请求的每个 URL 上,flask-security 库都会发送两个数据库查询:
select ... from user where user.id = 'the user identifier'
select ... from role, roles_users ...
我认为这是一个性能问题,我喜欢尽量减少这些查询。 我不知道我是否缺少配置功能。
如果不进行进一步优化(例如使用 Redis 缓存 SQL 响应或用户对象),我认为您无法避免第一个请求。在大多数情况下,您需要有关用户的数据,并且您不希望将这些数据存储在用户的会话 cookie 中。同样,您可以使用 Redis 之类的东西在服务器端存储这些信息,并通过会话 ID 进行索引。
但是您可能可以使用 JOIN 来避免第二个请求。通过同时执行第一个和第二个请求,将为您节省一些传输时间+数据库将能够选择合适的查询计划。
一种选择可能是覆盖 Flask-Login 的
user_loader
。不过,请参阅 this 讨论,了解为什么通常需要在每个请求上加载用户信息。
这就是 Flask-Security 实现
user_loader
的方式。
def _user_loader(user_id):
return _security.datastore.find_user(id=user_id)
这最终会产生一个 SQL 查询。
对于后代,这里如何启用对
sqlalchemy
发出的 SQL 查询的跟踪(调试):
import logging
logging.basicConfig()
logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)
另一个解决方案,也许有点过度设计,是为用户和角色拥有一个单独的 SQL-lite 数据库(用于 Flask-Login、Flask-Security 等)。在这种情况下,您将有 ~0 latency
用于读取。
init.py 中的代码:
# Override user_loader
@security.login_manager.user_loader
def user_loader(user_id):
if request.path.startswith('/static/'):
return None
return user_datastore.find_user(fs_uniquifier=user_id)