我正在使用Flask构建一个应用程序,但不太了解WSGI及其基于HTTP的框架Werkzeug。当我使用gunicorn和4个工作进程来启动Flask应用程序时,这是否意味着我可以处理4个并发请求?
我的意思是并发请求,并不是每秒请求数或其他任何内容。
运行开发服务器时,通过运行app.run()
命令,你得到的是一个单个同步进程,这意味着最多只能处理一个请求。
如果将Gunicorn放在默认配置中,并增加--workers
的数量,你将获得一些由Gunicorn管理的进程,每个进程都像app.run()
开发服务器一样运行。4个工作进程等于4个并发请求。这是因为Gunicorn默认使用包含sync
工作器类型的方式。
需要注意的是,Gunicorn还包括异步工作进程,即eventlet
和gevent
(还有tornado
,但最好与Tornado框架一起使用)。通过使用--worker-class
标志来指定其中一个异步工作进程,你将获得Gunicorn管理的一些异步进程,每个进程都管理自己的并发性。这些进程不使用线程,而是使用协程。基本上,在每个进程内,仍然只能同时发生1件事情(1个线程),但当对象正在等待外部进程完成(例如数据库查询或等待网络I/O)时,对象可以被“暂停”。
这意味着,如果你使用Gunicorn的异步工作进程,每个工作进程可以同时处理多个请求。最佳工作进程数量的确定取决于你的应用程序性质、其环境、运行硬件等等。更多详细信息可以在Gunicorn设计页面以及gevent工作方式说明上找到。
目前有一种比已提供的解决方案简单得多的方法。当您运行应用程序时,只需将threaded=True
参数传递给app.run()
调用即可:
app.run(host="your.host", port=4321, threaded=True)
根据我们在Werkzeug文档中所见,另一个选项是使用processes
参数,它接收大于1的数字,表示处理并发进程的最大数量:
- threaded - 进程是否应将每个请求分配给单独的线程?
- processes - 如果大于1,则在新进程中处理每个请求,直到达到此最大并发进程数。
类似这样:
app.run(host="your.host", port=4321, processes=3) #up to 3 processes
注意: 在Flask文档中,关于run()
方法指出在生产环境中使用它是不被推荐的,因为(引用): "虽然轻量且易用,但Flask内置的服务器在生产环境中不适合使用,因为它无法很好地扩展。"
然而,他们指向了他们的部署选项页面,以获取建议的生产环境下的解决方案。
Flask每次只能处理一个线程的请求。如果你有2个进程,每个进程有4个线程,那就是8个并发请求。
Flask不会生成或管理线程或进程,这是WSGI网关(例如gunicorn)的责任。
不,你绝对可以处理更多。
重要的是要记住,在深层次上,假设你正在运行单核机器,CPU 实际上只能同时运行一条指令*。
也就是说,CPU 只能执行非常有限的一组指令,并且它不能在每个时钟周期内执行多个指令(许多指令甚至需要多个周期)。
因此,我们在计算机科学中谈论的大多数并发都是软件并发。换句话说,有许多软件实现层将底层 CPU 抽象出来,使我们认为我们正在同时运行代码。
这些“东西”可以是进程,它们是以单位代码形式并发运行的,每个进程都认为自己在自己的世界中运行,具有自己的非共享内存。
另一个例子是线程,它们是进程内的代码单元,也允许并发。
你的 4 个工作进程之所以能够处理超过 4 个请求,是因为它们会启动线程来处理越来越多的请求。
实际请求限制取决于所选择的 HTTP 服务器、I/O、操作系统、硬件、网络连接等。
祝你好运!
*指令是 CPU 可以运行的基本命令。例如-将两个数字相加,从一个指令跳转到另一个指令