Flask处理POST请求时无法正常保存文件问题求助
Flask + Gunicorn 文件上传file.save()阻塞排查方案
检查文件系统与存储挂载
- 先确认目标磁盘可用空间:执行
df -h查看保存路径所在分区剩余空间,排除磁盘满的情况。 - 若用EC2挂载的EBS卷,检查CloudWatch里的EBS指标(队列长度、IO延迟),确认IOPS是否达标,避免突发IO耗尽导致阻塞。
- 验证保存目录权限:确保Gunicorn运行用户(如ec2-user、www-data)对目标目录有读写权限,执行
ls -ld /path/to/save查看,必要时用chown或chmod调整。 - 直接在服务器测试文件写入:执行
echo "test" > /path/to/save/test.txt,看是否能立即完成,排除文件系统本身的问题。
- 先确认目标磁盘可用空间:执行
调整Gunicorn配置
- 切换异步worker:默认sync worker处理大文件易阻塞,安装gevent后启动命令加
-k gevent,比如gunicorn -w 4 -k gevent app:app。 - 增大worker超时:设置
--timeout 120延长超时时间,同时检查Gunicorn日志是否有worker被强制杀死的记录。 - 禁用sendfile:启动时加
--sendfile off,避免sendfile机制导致的缓冲延迟。
- 切换异步worker:默认sync worker处理大文件易阻塞,安装gevent后启动命令加
重写文件保存逻辑
- 手动分块写入并强制刷新:替代
file.save(),直接操作文件流并强制刷盘,示例代码:import os def save_file(file, save_path): with open(save_path, 'wb') as f: chunk_size = 4096 while True: chunk = file.stream.read(chunk_size) if not chunk: break f.write(chunk) # 强制刷新缓冲区到磁盘 f.flush() os.fsync(f.fileno()) - 移除额外中间件:暂时去掉Flask-Uploads、自定义请求拦截等组件,测试基础上传逻辑是否正常。
- 手动分块写入并强制刷新:替代
系统级排查
- 实时监控磁盘IO:执行
iostat -x 1查看%util(磁盘使用率)和%iowait(IO等待时间),数值过高说明磁盘IO瓶颈。 - 检查进程文件句柄:用
lsof -p <gunicorn_worker_pid>查看worker进程打开的文件,确认是否有句柄占用目标保存文件。 - 临时关闭SELinux:执行
setenforce 0,测试是否能正常保存,若有效再配置SELinux规则或永久关闭。
- 实时监控磁盘IO:执行
内容的提问来源于stack exchange,提问作者METALNAVY
相关产品推荐
相关产品推荐

