我可以单独使用Flask app.run()服务多个客户端吗?

我知道我可以将Flask与Apache或其他web服务器连接起来。但是,我正在考虑将Flask作为一个独立的服务器,同时为多个客户端提供服务。

这可能吗?我是否必须处理生成多个线程并管理它们?

245373 次浏览

在Flask中使用简单的app.run()在一个线程上创建一个同步服务器,一次只能服务一个客户端。正是出于这个原因,它适用于低需求的受控环境(即开发、调试)。

生成线程并自己管理它们可能也不会让你走得太远,因为Python GIL

也就是说,你仍然有一些不错的选择。Gunicorn是一个可靠的,易于使用的WSGI服务器,它可以让你生成多个worker(独立的进程,所以没有GIL担忧),甚至附带异步的工人,它将加快你的应用程序(并使它更安全),而你几乎不需要做任何工作(特别是使用Flask)。

不过,即使是Gunicorn也不应该直接公开曝光。在生产中,它应该用于更健壮的HTTP服务器后面;nginx倾向于适合Gunicorn和Flask。

flask.Flask.run接受额外的关键字参数(**options),它将这些参数转发给werkzeug.serving.run_simple——其中两个参数是threaded(一个布尔值)和processes(你可以将其设置为一个大于1的数字,以便让werkzeug生成多个进程来处理请求)。

从Flask 1.0开始,threaded默认为True,因此对于Flask的最新版本,默认的开发服务器将能够默认地同时为多个客户端服务。对于较旧版本的Flask,你可以显式地传递threaded=True来启用此行为。

例如,你可以这样做

if __name__ == '__main__':
app.run(threaded=True)

以一种与旧Flask版本兼容的方式使用线程处理多个客户端,或者

if __name__ == '__main__':
app.run(threaded=False, processes=3)

告诉Werkzeug生成三个进程来处理传入的请求,或者只是

if __name__ == '__main__':
app.run()

如果你知道你将使用Flask 1.0或更高版本,可以使用线程处理多个客户端。

也就是说,Werkzeug的serving.run_simple包装了标准库的wsgiref包——这个包包含了一个WSGI的参考实现,而不是一个生产就绪的web服务器。如果你打算在生产中使用Flask(假设"production"不是一个低流量的内部应用程序,并发用户不超过10个),确保它站在一个真正的web服务器后面(参见Flask的文档中题为部署选项的部分,以获得一些建议的方法)。

2020年的小贴士:

从Flask 1.0开始,它默认启用多线程(),你不需要做任何事情,只需要升级它:

$ pip install -U flask

如果你正在使用flask run而不是旧版本的app.run(),你可以使用命令选项(--with-threads/--without-threads)控制线程行为:

$ flask run --with-threads

它与app.run(threaded=True)相同