windows flask 多进程高并发

文章讲述了作者在Windows环境下使用Flask封装Python函数时遇到的并发问题,尝试了多线程、多进程、gevent等方法,并最终通过启动多个独立的Flask服务来实现负载均衡,以提高响应速度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在做的一个项目,需要将十几个python函数封装程flask服务供外界调用,每个函数之间没有什么关系,相互独立。虽然感觉不是很难,但因为用的windows系统,遇到的坑比较多,在此一一总结一下。

flask偶尔出现卡死问题

上一篇文章

不能高并发问题

因为十几个函数都要被调用,而且调用量不小,对响应时效性有较高要求,需要能充分利用CPU并行计算,采用了如下几个解决方法

1.flask + gevent + multiprocess + wsgi

在网上搜到这个解决方案
但不知道是系统原因还是我的算法原因,运行之后发现CPU占用量比较低,而且同时收到服务请求后是串行计算并返回的。看来这种方法在我这种情况下并不适用。

2.设置多线程

还有一个解决方法是代码运行时设置多线程,即输入命令
python 文件名.py runserver --threaded
但发现依然没有并行计算

3.设置多进程

这个解决方案是在代码的app.run()函数中设置process=n,n就是你想要的进程数。但设置之后报错,说是不能同时设置多线程和多进程。然后又在app.run()中设置threaded=False,发现又报错,可能是这个功能只支持linux系统而不支持windows

还看到nginx和gunicorn的方法,但是不知道这个对windows是否支持,而且好像有点麻烦就没有试

4.手动负载均衡

通过测试发现一个现象,就是flask并非完全串行,当同时接收到2个请求,如果执行第一个请求会占用计算资源,那么就是算完第一个再算第二个,而如果第一个请求的计算是等待(比如time.sleep)或者挂起状态,则会同时去处理第二个请求而不用等到第一个请求返回结果。
因此想到了一个解决方法,就是每个函数都单独启一个flask服务,对于耗时比较长的函数根据需求多启几个服务,每个服务设置的端口号不同,然后再启动一个对外的flask服务,外界所有请求都发送到这一个flask端口,然后这个端口内部再向对应的flask服务发送请求。
原始flask代码:

from flask import Flask, render_template
from gevent.pywsgi import WSGIServer
from gevent import monkey
import time
import json

monkey.patch_all()
app = Flask(__name__)

@app.route('/')
def connect():
	return "connected test"

@app.route('/index')
def index_test():
	time0 = time.time()
	for i in range(10000):
		j = list(range(1000))
	print(time.time() - time0)
	res = {'data':1}
	res = json.dumps(res)
	return res

if __name__ == "__main__":
	server  = WSGIServer(("0.0.0.0", 5000), app)
	print("Server started")
	server.serve_forever()

测试调用代码:

import requests
from threading import Thread
import time
def req():
    time0 = time.time()
    res = requests.get('http://127.0.0.1:5000/index')
    print(time.time() - time0)
    # print(res.text)
for i in range(5):
    th = Thread(target=req)
    th.start()

结果:
fask端显示的结果为

0.5939996242523193
127.0.0.1 - - [2023-10-12 09:49:03] "GET /index HTTP/1.1" 200 127 0.600002
0.48799610137939453
127.0.0.1 - - [2023-10-12 09:49:04] "GET /index HTTP/1.1" 200 127 0.488996
0.5429947376251221
127.0.0.1 - - [2023-10-12 09:49:04] "GET /index HTTP/1.1" 200 127 0.544997
0.4839961528778076
127.0.0.1 - - [2023-10-12 09:49:05] "GET /index HTTP/1.1" 200 127 0.485996
0.4319908618927002
127.0.0.1 - - [2023-10-12 09:49:05] "GET /index HTTP/1.1" 200 127 0.434000

请求发送端显示的结果是

1.0300004482269287
1.3990015983581543
1.8730018138885498
2.3450255393981934
2.831998586654663

收到返回的时间却在逐渐增加,说明没有并行计算

改进代码:
入口flask代码:

from flask import Flask, render_template
from gevent.pywsgi import WSGIServer
from gevent import monkey
import requests
import time
import json

monkey.patch_all()
app = Flask(__name__)
path_num = {'num':-1}
@app.route('/')
def connect():
	return "connected test"

@app.route('/index')
def index_test():
	# time0 = time.time()
	# for i in range(10000):
	# 	j = list(range(1000))
	# print(time.time() - time0)
	# res = {'data':1}
	# res = json.dumps(res)
	if path_num['num'] > 4:
		path_num['num'] = 0
	else:
		path_num['num'] += 1
	num = path_num['num']
	url = f'http://127.0.0.1:{9030+num}/index'
	res = requests.post(url=url)
	return res.text

if __name__ == "__main__":
	server  = WSGIServer(("0.0.0.0", 5000), app)
	server.serve_forever()
	# app.run()


算法flask代码

from flask import Flask, render_template
from gevent.pywsgi import WSGIServer
from gevent import monkey
import time
import json

monkey.patch_all()
app = Flask(__name__)

@app.route('/')
def connect():
	return "connected test"

@app.route('/index')
def index_test():
	time0 = time.time()
	for i in range(10000):
		j = list(range(1000))
	print(time.time() - time0)
	res = {'data':1}
	res = json.dumps(res)
	return res

if __name__ == "__main__":
	server  = WSGIServer(("0.0.0.0", 9030), app)
	print("Server started")
	server.serve_forever()
	# app.run()

这里的算法flask代码启动了5个,接口分别是9030~9034
用同样的方式测试,返回的结果为

0.0500025749206543
0.05100274085998535
0.050002098083496094
0.05200028419494629
0.062003135681152344

差不多同时返回

总结

虽然最后一种方式有点麻烦,但可以解决现有问题,其中算法flask服务启动的越多性能越好。

以下是使用多进程实现 PyWebview 和 Flask 的完整代码。我们将 Flask 应用程序运行在一个独立的进程中,同时使用 PyWebview 创建桌面应用程序窗口。 ### 完整代码 ```python from flask import Flask, render_template_string import multiprocessing import webview import time # 创建Flask应用 app = Flask(__name__) # 定义HTML内容 html_content = """ <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>PyWebview Flask MultiProcess Example</title> </head> <body> <h1>Hello from Flask and PyWebview with Multiprocessing!</h1> <p>This is a simple example of embedding a Flask app inside a desktop application using PyWebview in a multi-process setup.</p> </body> </html> """ @app.route('/') def index(): return render_template_string(html_content) def start_flask(): """启动Flask应用""" app.run(port=5000) def main(): # 启动Flask服务器在一个单独的进程中 flask_process = multiprocessing.Process(target=start_flask) flask_process.daemon = True # 设置为守护进程,主程序退出时自动终止 flask_process.start() # 等待Flask启动完成(可以适当调整等待时间) time.sleep(2) # 创建webview窗口 webview.create_window('PyWebview Flask MultiProcess App', 'http://127.0.0.1:5000') webview.start() # 当webview关闭时,终止Flask进程 flask_process.terminate() if __name__ == '__main__': main() ``` --- ### 解释 1. **Flask 应用**: - 我们创建了一个简单的 Flask 应用程序,并定义了一个路由 `/`,返回一个 HTML 页面。 - `render_template_string` 用于直接渲染 HTML 字符串。 2. **多进程**: - 使用 `multiprocessing.Process` 将 Flask 应用程序运行在一个独立的进程中。 - 设置 `flask_process.daemon = True`,使得当主程序退出时,Flask 进程会自动终止。 3. **延迟启动**: - 由于 Flask 需要一些时间来启动服务器,我们在调用 `webview.create_window` 之前添加了一个短暂的延迟(`time.sleep(2)`),以确保 Flask 服务已经准备好。 4. **PyWebview**: - 使用 `webview.create_window` 创建一个桌面应用程序窗口,并加载 Flask 提供的内容。 - 当用户关闭窗口时,`webview.start()` 会退出,此时我们调用 `flask_process.terminate()` 来终止 Flask 进程。 --- ### 注意事项 1. **端口冲突**:确保端口 5000 没有被其他程序占用。如果需要,可以更改 Flask 的端口号。 2. **跨平台兼容性**:此代码在 Windows、Linux 和 macOS 上均能正常运行,但需要注意不同操作系统对多进程的支持可能略有差异。 3. **性能优化**:对于高并发场景,可以考虑使用 Gunicorn 或其他 WSGI 服务器替代 Flask 内置服务器。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值