目录
1、Flask默认多线程执行
2、使用gevent.pywsgi实现
3、是用uWSGI服务器实现
1、Flask默认多线程执行
前言:在Flask的较早版本中,默认并不支持多线程模式。然而,从Flask 0.9版本开始,引入了多线程模式的支持,并且在后续版本中逐渐成为默认设置。到了Flask 1.0版本,多线程模式已经被明确设定为默认行为。也就是说现在的Flask版本都是默认支持多线程的。
1、我们可以测试一下现在的Flask是不是以多线程的方式执行的。
【测试环境】
- Flask:2.3.2
- python:3.9.10
示例代码:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
time.sleep(3)
return "hello world"
if __name__ == '__main__':
app.run(debug=True)
- 我们进入到app.run()函数的源码查看,它的参数描述是怎么样的:
所以通过上面源码我们可以知道,现在是支持多线程的,且参数threaded默认True,也就是我们无法通过app.run()这个入口通过设置threaded为False来使用单线程,但是我们可以改源码。
1、现在我们通过JMeter来发起请求,看看是不是并发的。
- 1、线程数设置为2
- 2、HTTP请求配置如下:
- 3、再添加一个结果查看树,来查看运行结果
- 4、发送请求,查看结果
从上面结果可以看出两个线程的响应时间是3秒左右,可以得出确实是并发执行的。
2、那我们再看看把threaded参数改为False的情况
- 1、同样的发送请求,查看结果
从上面结果可以看出线程1的响应时间是3秒左右,而线程2的响应时间是5.5左右,可见线程2是等待线程1执行完了再执行的,得出结论两个线程是串行的。
总结:对于比较小型的项目在生产环境中部署没有问题,实际应用中还是应该根据实际的项目,进行压力测试找到对应的系统容量;但是对于一些大型的项目,并发量比较高的场景,继续使用默认的配置就不合适了,这时候需要使用专门的Web服务器,如使用uWSgi,Nginx,Docker容器等部署方式解决高并发的问题。下面介绍一些常用的手段。
2、使用gevent.pywsgi实现
gevent.pywsgi.WSGIServer: 是 Gevent 库中的一个 WSGI 服务器实现,主要用于提供异步、协程支持的 Web 服务器功能。它与传统的 WSGI 服务器(如 werkzeug.serving.WSGIRequestHandler)不同,具有以下几个优势和适用场景:
作用与优势
1、异步处理请求:
- Gevent 使用绿色线程(协程)来处理 I/O 操作,这使得它在处理大量并发请求时表现得更加高效。
- 由于使用了事件驱动和协程模型,Gevent 可以在等待 I/O 操作完成时继续处理其他任务,从而减少了阻塞和等待时间。
2、高并发处理能力:
- WSGIServer 可以处理大量的并发连接,而不会因为线程或进程的上下文切换而导致性能下降。这对于需要处理大量并发请求的应用非常有用,例如实时聊天应用或高流量的 API 端点。
3、轻量级
- Gevent 的绿色线程比传统的操作系统线程要轻量,内存开销小,创建和销毁速度快。这使得它能够支持更多的并发任务而不消耗过多的资源。
4、简化协程编程:
- Gevent 提供了简单的协程编程接口,可以很容易地使用 gevent.sleep() 等方法来编写异步代码,而不需要深入了解底层的异步 I/O 细节。
5、与现有代码兼容:
- Gevent 可以与现有的同步代码兼容,通过猴子补丁(monkey patching)来让标准库的同步操作支持异步执行。这样,你可以在不完全重写代码的情况下引入异步特性。
使用场景
1、高并发 Web 应用:
- 适用于需要处理大量并发请求的 Web 应用,如大型 API 服务或高流量的 Web 服务器。
2、实时应用:
- 例如聊天应用、实时数据推送服务、在线游戏等,这些应用需要处理大量并发连接和实时通信。
3、长连接服务:
- 对于需要保持长时间连接的服务,如 WebSocket 服务器,Gevent 的异步处理特性能够提供更好的性能和扩展性。
4、I/O 密集型任务:
- 适用于那些主要由 I/O 操作(如网络请求、文件读取等)组成的应用,这类任务通常会受益于 Gevent 的异步处理能力。
代码示例:
from flask import Flask
from gevent import monkey
from gevent.pywsgi import WSGIServer
app = Flask(__name__)
@app.route('/')
def index():
time.sleep(1)
return "hello world"
monkey.patch_all()
if __name__ == '__main__':
# app.run(debug=True)
http_server = WSGIServer(('0.0.0.0', 5000), app)
http_server.serve_forever()
做个简单压力测试看看相比于上面默认情况的性能情况:
- 1、从下图可以看出使用了WSGIServer的明显QPS要比默认情况的要高;
- 2、默认情况下的错误率达到了17.3%,使用了WSGIServer的错误率为0
综上所述:使用了WSGIServer的性能明显优于默认使用多线程的情况
3、是用uWSGI服务器实现
注意:uwsgi 主要是为 Unix/Linux 系统设计的,并不直接在 Windows 上支持。
1、安装uWSGI【注意:这里是在Linux环境下】:
pip install uwsgi
2、创建uWSGI配置文件:
你可以创建一个INI格式的配置文件,比如uwsgi.ini
,并在其中指定Flask应用的设置。一个基本的配置文件示例如下:
[uwsgi]
module = your_flask_app:app
master = true
processes = 4
socket = 0.0.0.0:8000
chmod-socket = 660
vacuum = true
die-on-term = true
在这个配置文件中:
module
指定了你的Flask应用的模块和变量名(通常是app
)。master
启用了主进程管理。processes
设置了工作进程的数量。socket
定义了uWSGI服务器监听的地址和端口。chmod-socket
更改了socket的权限。vacuum
在服务器关闭时清理socket和PID文件。die-on-term
在接收到SIGTERM时立即退出。
3、启动uWSGI服务器:
使用uWSGI的配置文件启动服务器:
uwsgi --ini uwsgi.ini
这将根据uwsgi.ini
文件中的设置启动uWSGI服务器,并运行你的Flask应用。
4、访问应用:
打开浏览器,访问http://localhost:8000(或者你在配置文件中指定的其他地址和端口),你应该能够看到你的Flask应用正在运行。
5、停止uWSGI服务器:
要停止uWSGI服务器,你可以使用以下命令(假设你知道uWSGI主进程的PID):
kill -SIGTERM <uwsgi_pid>
或者,如果你使用的是uwsgi --ini方式启动的,并且想要优雅地停止服务器,你可以发送SIGINT信号(通常是Ctrl+C)到你启动uWSGI的终端会话。