当前位置: 首页 > news >正文

Flask 线上高并发部署方案实现

目录

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 Flaskapp = 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 WSGIServerapp = 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的终端会话。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • QT 数据导出到Excel
  • 启程与远征Ⅵ--制定 AI 战略?这还不够!
  • 【docker】docker资源管理
  • 基础 - 前端知识体系详解
  • 无人机里的陀螺仪/加速器/气压计/GPS详解
  • ubuntu22.04 mysql 移动数据目录后 systemctl start mysql无法启动的解决方案
  • 1. windows搭建Kafka教程
  • [nsight compute使用指南] 查看存储体冲突
  • Halcon阈值处理的几种分割方法
  • 【MySQL】事务管理
  • Redis单线程模式
  • stm32入门学习14-电源控制
  • vue2中使用i18n配置elementUi切换语言
  • 数学基础 -- 卷积与矩阵乘法的区别
  • 基于R语言遥感随机森林建模与空间预测;遥感数据处理与特征提取;数据分析与可视化
  • flask接收请求并推入栈
  • Flex布局到底解决了什么问题
  • Java-详解HashMap
  • JS笔记四:作用域、变量(函数)提升
  • Koa2 之文件上传下载
  • Laravel5.4 Queues队列学习
  • node学习系列之简单文件上传
  • python docx文档转html页面
  • Redis 中的布隆过滤器
  • Spring核心 Bean的高级装配
  • vue:响应原理
  • 创建一种深思熟虑的文化
  • 代理模式
  • 多线程事务回滚
  • 坑!为什么View.startAnimation不起作用?
  • 使用Gradle第一次构建Java程序
  • 我们雇佣了一只大猴子...
  • ​LeetCode解法汇总2583. 二叉树中的第 K 大层和
  • ​用户画像从0到100的构建思路
  • #我与Java虚拟机的故事#连载07:我放弃了对JVM的进一步学习
  • (1综述)从零开始的嵌入式图像图像处理(PI+QT+OpenCV)实战演练
  • (vue)el-checkbox 实现展示区分 label 和 value(展示值与选中获取值需不同)
  • (二)hibernate配置管理
  • (二)学习JVM —— 垃圾回收机制
  • (附源码)c#+winform实现远程开机(广域网可用)
  • (附源码)spring boot网络空间安全实验教学示范中心网站 毕业设计 111454
  • (附源码)ssm基于微信小程序的疫苗管理系统 毕业设计 092354
  • (七)微服务分布式云架构spring cloud - common-service 项目构建过程
  • (一)utf8mb4_general_ci 和 utf8mb4_unicode_ci 适用排序和比较规则场景
  • (转)LINQ之路
  • (转)ObjectiveC 深浅拷贝学习
  • (转载)在C#用WM_COPYDATA消息来实现两个进程之间传递数据
  • ./configure,make,make install的作用
  • .\OBJ\test1.axf: Error: L6230W: Ignoring --entry command. Cannot find argumen 'Reset_Handler'
  • .NET / MSBuild 扩展编译时什么时候用 BeforeTargets / AfterTargets 什么时候用 DependsOnTargets?
  • .NET Core跨平台微服务学习资源
  • .NET Framework 3.5中序列化成JSON数据及JSON数据的反序列化,以及jQuery的调用JSON
  • .net MVC中使用angularJs刷新页面数据列表
  • .net 怎么循环得到数组里的值_关于js数组
  • .NET 直连SAP HANA数据库