一个Flask进程接收多少个并发请求?


138

我正在用Flask构建一个应用程序,但是我对WSGI并不太了解,它是基于HTTP的Werkzeug。当我开始使用gunicorn和4个工作进程处理Flask应用程序时,这是否意味着我可以处理4个并发请求?

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

Answers:


183

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

通过将Gunicorn保留在其默认配置中并简单地增加Gunicorn的数量--workers,您所获得的实际上是一些流程(由Gunicorn管理),每个流程的行为都类似于app.run()开发服务器。4个工作人员== 4个并发请求。这是因为Gunicorn sync默认使用其包含的工作程序类型。

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

这意味着,如果您使用的是Gunicorn的异步工作程序之一,则每个工作程序一次最多可以处理多个请求。多少工人才是最好的,取决于您的应用程序的性质,其环境,运行的硬件等。有关更多详细信息,请参见Gunicorn的设计页面,并在其介绍页面上介绍gevent的工作方式


4
从19版开始,Gunicorn现在支持“真实”线程。请参阅thisthis
Filipe Correia

2
如何跟踪线程(或进程)之间共享哪些资源(以及如何共享)以及哪些资源完全分开?例如,当我要在由Gunicorn处理并在Flask处理程序中使用的多个进程之间共享巨大的数据结构时,我将如何处理?
Johann Petrak,

您问的@Johsm就像询问如何在操作系统中的不同进程之间共享数据。答案可以回答您的问题,因为进程不与其他进程共享其内存,因此您必须使用外部存储。Gunicorn在这里仅利用多处理CPU架构,而不能处理这些问题。
adkl

夏娃呢?这也适用于夏娃吗?
Eswar

2
烧瓶开发服务器在默认情况下,因为1.0版(使用线程github.com/pallets/flask/pull/2529
hychou

40

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

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

根据在werkzeug文档中可以看到的另一种选择是使用processes参数,该参数接收的数字> 1表示要处理的最大并发进程数:

  • 线程化–进程应在单独的线程中处理每个请求吗?
  • 进程–如果大于1,则将处理新进程中的每个请求,直到最大并发进程数。

就像是:

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

关于更多信息run()方法在这里,和博客文章,导致我找到解决方案和API引用。


注意:在Flask文档中,关于run()方法的方法表明不鼓励在生产环境中使用它,因为(quote):“虽然Flask轻巧易用,但其内置服务器不适合生产,因为它的扩展性不好”。

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


5
谢谢(你的)信息。重要的是要注意,运行文档指出不应在生产环境中使用它,表明它不符合安全性或性能要求。
Coffee_fan

1
@Coffee_fan你是对的。即使在最新的1.1.x上,他们也不愿这样做,而是建议在进行生产时检查其在“ 部署选项”上的页面。在答案中包括您的宝贵意见:)
DarkCygnus

33

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

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


9

不,您绝对可以处理更多。

重要的是要记住,假设您正在运行一台单核计算机,那么CPU实际上一次只能运行一条指令*。

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

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

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

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

您的4个辅助进程能够处理4个以上请求的原因是,它们将触发线程以处理越来越多的请求。

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

祝好运!

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


1
它是产于线或烧瓶中的古尼康吗?我发现没有证据支持这两种可能性。
jd。

1
当然,我了解有关进程的信息,但答案是根据需要产生了更多的线程。这就是我想要确认的内容。
jd。

4
“深入了解,假设您正在运行一台单核计算机,那么CPU实际上一次只能运行一条指令*”这在现代计算机上是不正确的。大多数现代CPU都是流水线超标量的,甚至单个内核都具有多个执行单元和一个指令解码器,该指令解码器将从软件方面看到的“机器代码”转换为实际的硬件微操作,并分配给各个执行单元。
Michael Geary

1
为了澄清,回想一下,实际上,CPU实际上确实直接在可执行文件(机器代码)中执行数字指令。每个CPU参考都有一个指令时序图,显示每个指令占用多少时钟周期,包括任何存储器参考。因此,您可以累加时间来知道任何一段代码将花费多长时间。现代CPU根本不是那样。BeagleBone是一个有趣的例外,它具有现代的超标量ARM处理器两个具有固定指令时序的老式“ PRU”处理器。
Michael Geary

1
为了澄清这一点,当我说“现代”时,我将其用作ARM / Intel / AMD芯片(流水线,超标量等)等处理器的宽松速记。当然,也有现代处理器以固定的时间运行每条指令,例如我提到的BeagleBone PRU和各种新的微控制器。(现在回到Gunicorn!)
Michael Geary
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.