Python3.6+Django1.11大文件上传后服务器响应缓慢问题
哎,这个问题我之前踩过坑!你描述的场景太典型了——文件明明已经存好、数据库也写完了,客户端却还要等半天才能收到响应,而且中断客户端不影响上传,说明问题出在服务器处理完上传后的环节。我帮你梳理几个最可能的原因和解决办法:
1. 最常见的元凶:同步执行的耗时后置操作
你有没有给Document模型绑定post_save信号?或者在form_valid方法里加了文件处理逻辑?比如上传完成后计算文件哈希、读取文件内容做校验、甚至病毒扫描——这些操作如果是同步在请求周期内执行的,那2GB的文件再次被读取一遍,刚好会消耗和上传差不多的时间(10秒),完美匹配你说的延迟!
举个例子,如果你有类似这样的代码:
from django.db.models.signals import post_save from django.dispatch import receiver import hashlib @receiver(post_save, sender=Document) def process_after_upload(sender, instance, created, **kwargs): if created: # 作死操作:读取整个2GB文件计算哈希 with open(instance.file.path, 'rb') as f: file_hash = hashlib.sha256(f.read()).hexdigest() instance.hash = file_hash instance.save()
这绝对会导致延迟!因为这段代码是在视图返回响应之前执行的,服务器必须等它做完才能给客户端发响应。
解决办法:把耗时操作异步化
用Celery或者Django自带的异步任务框架(Django 3.1+支持)把这些操作放到后台,视图处理完表单后直接返回响应,后台慢慢处理文件:
# 用Celery的示例 from celery import shared_task @shared_task def process_document_task(document_id): document = Document.objects.get(id=document_id) with open(document.file.path, 'rb') as f: file_hash = hashlib.sha256(f.read()).hexdigest() document.hash = file_hash document.save() # 在form_valid里调用异步任务 class DocumentCreate(CreateView): model = Document form_class = DocumentForm def form_valid(self, form): instance = form.save() # 把任务丢给Celery,立即返回响应 process_document_task.delay(instance.id) return super().form_valid(form)
2. 开发服务器runserver的性能瓶颈
Django自带的runserver是单进程单线程的(默认),处理大文件上传后,可能会有资源释放、缓冲区刷新的延迟——毕竟它只是给开发用的,不是生产级服务器。
解决办法:换生产级WSGI服务器测试
试试用gunicorn或者uwsgi启动服务,看延迟是否消失:
# 安装gunicorn pip install gunicorn # 启动服务 gunicorn your_project.wsgi:application
如果换了服务器后延迟没了,那就是runserver的锅,生产环境用正规服务器就行。
3. Django文件上传的临时文件清理延迟
Django处理大文件时,会先把文件写到临时目录(默认是系统的临时目录),然后再移动到upload_to指定的目录。如果临时目录的IO性能差,或者Django在返回响应前等待临时文件的清理,也可能导致延迟。
解决办法:配置专属临时上传目录
在settings.py里指定一个IO性能好的临时目录,避免和系统临时文件抢资源:
FILE_UPLOAD_TEMP_DIR = '/path/to/your/custom/temp/dir' # 同时可以调整内存上传阈值,超过就直接写临时文件 FILE_UPLOAD_MAX_MEMORY_SIZE = 2621440 # 2.5MB
4. 表单或视图里的冗余操作
检查你的ModelForm或者DocumentCreate视图,有没有在form_valid里做不必要的查询、数据处理——比如查询大量关联数据,或者自定义get_success_url时包含耗时操作?
解决办法:精简视图逻辑
确保form_valid里只做必要的操作:保存表单、触发异步任务,然后立即返回重定向响应,不要加多余的逻辑。
总结一下:90%的概率是请求周期内的同步耗时操作导致的,尤其是post_save信号里的文件处理。先排查这个,应该就能解决问题!
内容的提问来源于stack exchange,提问作者Guillaume Lebreton

