175

我正在用 Flask 构建一个应用程序,但我对 WSGI 及其 HTTP 基础 Werkzeug 了解不多。当我开始使用 gunicorn 和 4 个工作进程为 Flask 应用程序提供服务时,这是否意味着我可以处理 4 个并发请求?

我的意思是并发请求,而不是每秒请求数或其他任何东西。

4

4 回答 4

230

当运行开发服务器时——这是你通过运行得到的app.run(),你得到一个同步进程,这意味着一次最多处理一个请求。

通过在其默认配置中将 Gunicorn 放在其前面并简单地增加 的数量--workers,您得到的本质上是许多进程(由 Gunicorn 管理),每个进程的行为都类似于app.run()开发服务器。4 个工作人员 == 4 个并发请求。这是因为 Gunicornsync默认使用其包含的 worker 类型。

重要的是要注意 Gunicorn 还包括异步工作程序,即eventletgevent(以及tornado,但最好与 Tornado 框架一起使用,似乎)。通过使用--worker-class标志指定这些异步工作者之一,您将得到 Gunicorn 管理多个异步进程,每个进程管理自己的并发。这些进程不使用线程,而是使用协程。基本上,在每个进程中,一次仍然只能发生一件事(1 个线程),但对象在等待外部进程完成时可以“暂停”(想想数据库查询或等待网络 I/O)。

这意味着,如果您使用 Gunicorn 的一个异步工作器,每个工作器一次可以处理多个请求。多少工人最好取决于你的应用程序的性质、它的环境、它运行的硬件等。更多细节可以在Gunicorn 的设计页面和关于 gevent 如何工作的说明在它的介绍页面上找到。

于 2012-12-18T08:36:03.410 回答
58

目前有一个比已经提供的解决方案简单得多的解决方案。运行应用程序时,您只需将threaded=True参数传递给app.run()调用,例如:

app.run(host="your.host", port=4321, threaded=True)

根据我们在werkzeug 文档中看到的另一个选项是使用processes参数,它接收一个 > 1 的数字,表示要处理的最大并发进程数:

  • 线程化——进程是否应该在单独的线程中处理每个请求?
  • processes - 如果大于 1,则处理新进程中的每个请求,直到最大并发进程数。

就像是:

app.run(host="your.host", port=4321, processes=3) #up to 3 processes

run()有关该方法更多信息,以及引导我找到解决方案和 api 参考的博客文章。


注意:在有关run()方法的 Flask 文档中,不鼓励在生产环境中使用它,因为(引用):“虽然轻量级且易于使用,但 Flask 的内置服务器不适合生产,因为它不能很好地扩展。”

但是,他们确实指向他们的部署选项页面,以了解在进行生产时执行此操作的推荐方法。

于 2018-06-06T01:05:04.587 回答
37

Flask 将同时处理每个线程的一个请求。如果您有 2 个进程,每个进程有 4 个线程,那就是 8 个并发请求。

Flask 不会产生或管理线程或进程。这是 WSGI 网关(例如 gunicorn)的职责。

于 2012-06-08T05:31:58.537 回答
9

不 - 你绝对可以处理更多。

重要的是要深深记住,假设您运行的是单核机器,CPU 确实一次只运行一条指令*。

也就是说,CPU 只能执行非常有限的一组指令,并且每个时钟滴答不能执行超过一条指令(许多指令甚至需要超过 1 个滴答)。

因此,我们在计算机科学中谈论的大多数并发是软件并发。换句话说,有一些软件实现层从我们身上抽象出底层 CPU,让我们认为我们正在同时运行代码。

这些“事物”可以是进程,它们是并发运行的代码单元,每个进程都认为它在自己的世界中运行,具有自己的非共享内存。

另一个例子是线程,它是进程内的代码单元,也允许并发。

您的 4 个工作进程将能够处理超过 4 个请求的原因是它们将触发线程以处理越来越多的请求。

实际请求限制取决于选择的 HTTP 服务器、I/O、操作系统、硬件、网络连接等。

祝你好运!

*指令是 CPU 可以运行的非常基本的命令。示例 - 将两个数字相加,从一条指令跳转到另一条指令

于 2012-06-08T02:11:43.240 回答