Flask异步处理请求

2,448 阅读2分钟

这是我参与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 操作

flask

当然,如果要模型多并发请求的话,就需要写个脚本测试了,使用之前介绍过的 request 网络请求模块,这里就不多说了,参考链接 xugaoxiang.com/2020/11/28/…

参考资料