我正在用 Flask 构建一个应用程序,但我对 WSGI 及其 HTTP 基础 Werkzeug 了解不多。当我开始使用 gunicorn 和 4 个工作进程为 Flask 应用程序提供服务时,这是否意味着我可以处理 4 个并发请求?
我的意思是并发请求,而不是每秒请求数或其他任何东西。
当运行开发服务器时——这是你通过运行得到的app.run()
,你得到一个同步进程,这意味着一次最多处理一个请求。
通过在其默认配置中将 Gunicorn 放在其前面并简单地增加 的数量--workers
,您得到的本质上是许多进程(由 Gunicorn 管理),每个进程的行为都类似于app.run()
开发服务器。4 个工作人员 == 4 个并发请求。这是因为 Gunicornsync
默认使用其包含的 worker 类型。
重要的是要注意 Gunicorn 还包括异步工作程序,即eventlet
和gevent
(以及tornado
,但最好与 Tornado 框架一起使用,似乎)。通过使用--worker-class
标志指定这些异步工作者之一,您将得到 Gunicorn 管理多个异步进程,每个进程管理自己的并发。这些进程不使用线程,而是使用协程。基本上,在每个进程中,一次仍然只能发生一件事(1 个线程),但对象在等待外部进程完成时可以“暂停”(想想数据库查询或等待网络 I/O)。
这意味着,如果您使用 Gunicorn 的一个异步工作器,每个工作器一次可以处理多个请求。多少工人最好取决于你的应用程序的性质、它的环境、它运行的硬件等。更多细节可以在Gunicorn 的设计页面和关于 gevent 如何工作的说明在它的介绍页面上找到。
目前有一个比已经提供的解决方案简单得多的解决方案。运行应用程序时,您只需将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 的内置服务器不适合生产,因为它不能很好地扩展。”
但是,他们确实指向他们的部署选项页面,以了解在进行生产时执行此操作的推荐方法。
Flask 将同时处理每个线程的一个请求。如果您有 2 个进程,每个进程有 4 个线程,那就是 8 个并发请求。
Flask 不会产生或管理线程或进程。这是 WSGI 网关(例如 gunicorn)的职责。
不 - 你绝对可以处理更多。
重要的是要深深记住,假设您运行的是单核机器,CPU 确实一次只运行一条指令*。
也就是说,CPU 只能执行非常有限的一组指令,并且每个时钟滴答不能执行超过一条指令(许多指令甚至需要超过 1 个滴答)。
因此,我们在计算机科学中谈论的大多数并发是软件并发。换句话说,有一些软件实现层从我们身上抽象出底层 CPU,让我们认为我们正在同时运行代码。
这些“事物”可以是进程,它们是并发运行的代码单元,每个进程都认为它在自己的世界中运行,具有自己的非共享内存。
另一个例子是线程,它是进程内的代码单元,也允许并发。
您的 4 个工作进程将能够处理超过 4 个请求的原因是它们将触发线程以处理越来越多的请求。
实际请求限制取决于选择的 HTTP 服务器、I/O、操作系统、硬件、网络连接等。
祝你好运!
*指令是 CPU 可以运行的非常基本的命令。示例 - 将两个数字相加,从一条指令跳转到另一条指令