为什么 flask run 不建议用于生产环境?

2020-07-21 10:52:23 +08:00
 feng32

如果预计的负载小于 1 qps,可以安全地直接使用 flask run 提供服务吗?

FLASK_APP=admin.py flask run
 * Serving Flask app "admin.py"
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
5156 次点击
所在节点    程序员
19 条回复
la2la
2020-07-21 11:11:25 +08:00
做个性能测试就体现出来了。
welkinzh
2020-07-21 11:19:47 +08:00
你说的这个情况真要用也不是不行,不过裸跑 flask 没有服务挂了自动重启,访问量上来了自动扩容等等功能
minami
2020-07-21 11:28:20 +08:00
用 gunicorn 啊,多好用
hakono
2020-07-21 11:34:44 +08:00
不让用在生产环境是因为这么搞性能很差
但楼主你这负载小于 1qps 。。。。直接 flask run 没问题
renmu123
2020-07-21 12:40:48 +08:00
推荐 gunicorn,很方便,一个命令就可以了,再套层 NGINX
GrayXu
2020-07-21 15:45:40 +08:00
加一个中间层其实要做的事情很少,不过负载量小的话当然也无所谓了
wuwukai007
2020-07-21 15:46:40 +08:00
开发服务器长时间运行有大概率会假死的,
hunk
2020-07-21 15:52:36 +08:00
@renmu123 gunicorn nginx +1
Hardrain
2020-07-21 16:11:21 +08:00
因为 werkzeug 的进程模型没有考虑生产环境需要的性能

生产环境应该用 gunicorn/uwsgi 这类 wsgi 服务器,或者 mod_wsgi 这种嵌入 Web 服务器的实现
Firxiao
2020-07-21 17:16:46 +08:00
太长不看: 编写一个健壮、快速和可伸缩的 HTTP 服务器绝非易事,它需要的不仅仅是“支持多线程多进程”。

[文档]( https://werkzeug.palletsprojects.com/en/1.0.x/serving/)说的是你不应该在生产中使用开发服务器:

开发服务器不打算用于生产系统。它是专门为开发目的而设计的,在高负载下性能很差。

这并不妨碍您在 werkzeug 上构建您的应用程序(希望如此),您只是想使用可用于生产的 HTTP 服务器进行部署。

至于原因,上面已经清楚地说明了:此开发服务器的设计不是为了在负载下正确执行,而是作为一种实际的开发工具。正确处理负载是一个相当复杂的问题,这就是为什么有专门的 HTTP 服务器,如 nginx, apache 等——它们几乎都是用 C 语言编写的——关注稳定性和性能。因此,如果您试图在生产环境中使用 werkzeug 的开发服务器,那么它将在负载下变得非常慢,以至于您的站点将完全无法使用。您可能还会遇到内存使用问题(这可能会导致您的服务器崩溃)和安全问题——这两个问题对于一个专用的、经过调试和优化的 HTTP 服务器来说是很难正确处理的。

搬运+有道翻译
https://stackoverflow.com/questions/50152641/why-cant-use-werkzeug-in-production
volvo007
2020-07-21 17:54:26 +08:00
这是 flask 和 Django 很不一样的地方,我一开始也困惑了很久

简单说,flask 需要有一个中间件( wsgi )去让 flask 进程挂靠,flask 的 app 才能跑起来

为了开发方便,flask 自己也实现了一个简单的 wsgi 组件,但这个组件性能很差。你如果用 vscode 开发,就会发现直接跑的话,cpu 负载一直很高,即使什么也没做

所以用 gunicorn 这种中间件,设置一下配置文件之后,让多个 flask app 挂靠在 gunicorn 上就可以了

不过只用 gunicorn,又会出现如果有多个 gunicorn,你要配置不同的端口,访问的时候就麻烦了。所以可以在前面再套一个 nginx 反向代理,这样用户访问的时候也不用输端口了
noahzh
2020-07-21 18:59:27 +08:00
就是把 http 请求翻译成 python 能识别的请求,楼上都没有说到点子上,生产环境不推荐的原因是,无论你请求多小,你要保证的是任何时候请求来了能处理.werkzeug 只是一个满足功能的开发工具,但是没有任何人能保证他的可用性.
julyclyde
2020-07-22 10:44:58 +08:00
@volvo007 django 也是“被”调用的资格啊。和 flask 一样的
mywaiting
2020-07-22 11:01:25 +08:00
Tornado 就没有这个困扰,自身就是生产环境的 Server 的实现(当然也有兼容 WSGI 的实现)

性能还相当不错,典型的放心去爱良心产品
ruanimal
2020-07-22 14:23:39 +08:00
@volvo007 为啥有“多个 gunicorn”,gunicorn 可以多进程啊
SenLief
2020-07-22 15:18:11 +08:00
gunicorn 是个不错的工具,不过这个无法在 windows 上跑,我看 flask 官方快速开始文档使用了 waitress,纯 py 实现的 wsgi 框架也还蛮好用的。
volvo007
2020-07-22 17:31:49 +08:00
@ruanimal 其实这也是我没搞懂的一个地方。我这里说的多线程当然不是 worker 参数分配给每个 gunicorn 服务的线程数量;而是说如果我有两个完全不同的 site 需要部署,那我的理解是我需要跑两个 gunicorn 服务来将不同的 site 分离开

但我并不清楚要这么做的最佳实践是什么……

另一个常见情况是,有一个 /home 的入口,通过 /home 可以跳转到其他 app 比如 /func1, /func2 ;我现在做的办法比较蠢,就是一个 app 跑一个 gunicorn 服务,然后每个服务分配一个端口,再通过 nginx 反向代理访问。有没有办法把 多个 app 放到一个 gunicorn 服务下面跑呢?

网上找了不少资料。当然可以通过在 main_app 里面 import app1, app2 来把 其他 app.py 里的东西拉过来搞;但很多也是直接运行多个 gunicorn 服务,没搞清楚这种情况的最佳实践是什么
ruanimal
2020-07-23 10:18:59 +08:00
@volvo007 你这个是分 app,flask 是用 blueprint 来做的 https://flask.palletsprojects.com/en/1.1.x/blueprints/

部署的时候用一个 gunicorn 就好了
volvo007
2020-07-23 11:23:14 +08:00
@ruanimal 多谢。搜了下例子,这个类的出发点解决了我的问题,不过现在还没办法自己写。回头练练

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/691828

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX