Heroku gunicorn flask登录无法正常工作

8
我有一个使用Flask-Login进行认证的Flask应用程序。在本地使用flask内置的Web服务器和本地运行的gunicorn都可以正常工作。但是当它部署到Heroku上时,它会出现故障,有时会成功登录,有时则不会。当我在几秒钟内成功登录后,我的会话就会被销毁,并自动注销我的登录状态。这种情况应该只会在用户注销时发生。
下面是我视图中的代码片段,可能与此相关:
@app.before_request
def before_request():
    g.user = current_user

# I have index (/) and other views (/new) decorated with @login_required

我可能遇到了与这个相似的问题。目前该问题还没有答案,从评论中可以看出,作者只是通过运行python app.py来启动他的应用程序,使用了Flask内置的Web服务器。但是我似乎无法重复他的解决方法,因为运行app.run(host='0.0.0.0')会在端口5000上运行应用程序,而由于权限的限制,我似乎无法设置port=80
日志中除了我应该验证时没有任何有用的信息。
当我成功验证并尝试交替导航到/new/时,部分日志如下:
2016-09-25T06:57:53.052378+00:00 app[web.1]: authenticated - IP:10.179.239.229
2016-09-25T06:57:53.455145+00:00 heroku[router]: at=info method=GET path="/" host=testdep0.herokuapp.com request_id=c7c8f4c9-b003-446e-92d8-af0a81985e72 fwd="124.100.201.61" dyno=web.1 connect=0ms service=116ms status=200 bytes=6526
2016-09-25T06:58:11.415837+00:00 heroku[router]: at=info method=GET path="/new" host=testdep0.herokuapp.com request_id=ae5e4e29-0345-4a09-90c4-36fb64785079 fwd="124.100.201.61" dyno=web.1 connect=0ms service=7ms status=200 bytes=2552
2016-09-25T06:58:13.543098+00:00 heroku[router]: at=info method=GET path="/" host=testdep0.herokuapp.com request_id=47696ab9-57b9-4f20-810a-66033e3e9e50 fwd="124.100.201.61" dyno=web.1 connect=0ms service=8ms status=200 bytes=5982
2016-09-25T06:58:18.037766+00:00 heroku[router]: at=info method=GET path="/new" host=testdep0.herokuapp.com request_id=98912601-6342-4d71-a106-26056e4bbb21 fwd="124.100.201.61" dyno=web.1 connect=0ms service=3ms status=200 bytes=2552
2016-09-25T06:58:19.619369+00:00 heroku[router]: at=info method=GET path="/" host=testdep0.herokuapp.com request_id=2b04d31f-93a2-4653-83a4-f95ca9b97149 fwd="124.100.201.61" dyno=web.1 connect=0ms service=3ms status=302 bytes=640
2016-09-25T06:58:19.953910+00:00 heroku[router]: at=info method=GET path="/login?next=%2F" host=testdep0.herokuapp.com request_id=e80d15cd-e9ad-45ff-ae54-e156412fe4ff fwd="124.100.201.61" dyno=web.1 connect=0ms service=3ms status=200 bytes=2793

Procfile:

web:使用gunicorn运行app:app

4个回答

16
问题通过向gunicorn添加--preload选项来解决。我不完全确定这如何解决问题,如果有人能够解释一下那将不胜感激。
更新的 Procfile: web: gunicorn app:app --preload

1
这解决了我的问题!有关预加载的更多信息,请参见此处:https://docs.gunicorn.org/en/stable/settings.html - Taylor D
这完全解决了问题。我也不知道为什么,但感谢您的帮助。 - ExoWanderer
看起来这是一个很酷的东西,也许它一遍又一遍地选择了相同的线程,或者记住了最近使用的线程上下文,你在生产中有看到任何性能瓶颈吗? - Prince Roshan

1

跟随krato的建议(这使得我的应用程序能够工作),我的应用程序仍然不能完美地工作。即使第一次登录成功,我仍然可以继续刷新,最终会被注销。因此,在阅读了this article之后,我将gunicorn设置为只使用1个worker,如下所示:

web: gunicorn -w 1 :app --preload

这似乎解决了问题。


顺便说一下,这将只运行您的Web应用程序的一个实例,这基本上打败了使用gunicorn的目的。 - AldaronLau

0

0

为了帮助那些遇到这个问题的人,我想提供一些指针。

这个问题可能是由于生产环境中的多线程环境引起的。

在处理任何请求上下文之前,flask-login查询load_user,因此您必须根据您的生产环境自定义它。

您必须实现类似以下内容的东西,这取决于您如何在请求上下文的处理之前向flask-login提供用户对象。

@login_manager.user_loader
def load_user(id):
    app.logger.debug(f"session {session}")
    if session:
        return User.query.filter_by(id=session['_user_id']).first() 

检查_load_user的确切工作方式,因为它已被调用以加载current_user https://github.com/maxcountryman/flask-login/blob/main/src/flask_login/login_manager.py#L301

在文档中查看此内容 https://flask-login.readthedocs.io/en/latest/#how-it-works

检查此内容,也许您只需要在cookie中添加“记住我” https://github.com/maxcountryman/flask-login/blob/main/src/flask_login/login_manager.py#L331


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接