这是我参与11月更文挑战的第10天,活动详情查看:2021最后一次更文挑战
软硬件环境
- ubuntu 16.04 64bit
- python3
- flask
问题描述
在使用 web 框架 flask 的时候,经常需要提供 HTTP POST 接口来处理一些数据,而当多个客户端同时连接上来的时候,如何并行地处理这些任务经常困扰着我们,常见的处理方法是将请求放到一个线程池或者进程池中进行管理。本文就来利用 python 中自带的 concurrent.futures 来实现这个功能,这个模块具有线程池和进程池、管理并行编程任务、处理非确定性的执行流程、进程或线程同步等功能
代码实践
下面以 flask 服务接收图片文件为例,具体可以看看代码行间的注释
import os
import time
from flask import Flask, request
from werkzeug.utils import secure_filename
from concurrent.futures import ThreadPoolExecutor
# app初始化
flask_app = Flask(__name__)
# 能接收的图片文件大小
flask_app.config['MAX_CONTENT_LENGTH'] = 2 * 1024 * 1024
# 同时处理的最大线程数,示例中使用线程池,也可以使用进程池ProcessPoolExecutor,使用方法类似
executor = ThreadPoolExecutor(10)
# 能接收的文件后缀名
ALLOWED_EXTENSIONS = set(['png','jpg','jpeg'])
# 允许接收的文件类型
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
# 只能接收POST方法
@flask_app.route('/uploadImageFile', methods=['POST'])
def uploadImageFile():
'''
HTTP POST, 接收发送过来的图片数据
:return:
'''
# multipart/form-data file --> key
file = request.files['longjing']
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
if not os.path.exists('temp'):
os.mkdir('temp')
file.save(os.path.join('temp', filename))
# 上传的是空文件
if os.stat(os.path.join('temp', filename)).st_size == 0:
os.remove(os.path.join('temp', filename))
return 'Empty image file.'
# 异步任务
executor.submit(do_job, filename)
# 直接返回
return 'POST success.'
else:
return "POST failed."
def do_job(filename):
'''
模拟的异步任务
:param filename:
:return:
'''
print('start do_job, file={}'.format(filename))
time.sleep(10)
print('finish do_job')
if __name__ == '__main__':
# 启动app
flask_app.run(host='0.0.0.0', port=8889)
使用 Postman 来模拟客户端的 POST 操作
当然,如果要模型多并发请求的话,就需要写个脚本测试了,使用之前介绍过的 request 网络请求模块,这里就不多说了,参考链接 xugaoxiang.com/2020/11/28/…