You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django FileResponse处理大文件崩溃,树莓派宕机求助

解决思路与建议

1. 重构备份流程,避免内存中处理大文件

  • 数据库导出直接写入磁盘:用mysqldump命令导出MariaDB,直接输出到临时文件,禁止在Python内存中缓存输出内容。示例调用:
    mysqldump -u 用户名 -p密码 数据库名 > /tmp/db_backup.sql
    
    用Pythonsubprocess执行时,指定stdout为磁盘文件对象,不要捕获输出到内存变量。
  • ZIP打包优先用磁盘文件:用系统zip命令直接打包磁盘上的文件到临时ZIP,或用Pythonzipfile.ZipFile以w模式写入磁盘,绝对禁止用BytesIO作为ZIP输出目标(会把整个6GB文件加载到内存)。

2. 优化Django文件响应配置

  • 显式设置FileResponse分块大小:初始化时指定chunk_size=65536(64KB),强制按块读取文件,避免一次性加载:
    from django.http import FileResponse
    
    def backup_download(request):
        backup_file = open('/tmp/backup.zip', 'rb')
        response = FileResponse(backup_file, chunk_size=65536)
        response['Content-Disposition'] = 'attachment; filename="backup.zip"'
        return response
    
  • 禁用缓冲类中间件:暂时关闭GZipMiddleware,大文件压缩会占用大量内存,若需压缩可让Nginx处理静态文件压缩逻辑。
  • 给Daphne设置内存上限:在systemd配置文件中添加MemoryLimit=4G(根据树莓派实际内存调整),避免进程耗尽内存拖垮系统。

3. 调整Nginx反向代理配置

  • 延长超时并关闭缓冲:在Nginx的location配置中添加以下参数,适配大文件下载的长时长需求,同时避免Nginx自身缓存响应占用内存:
    location / {
        proxy_pass http://localhost:8000;
        proxy_connect_timeout 600s;
        proxy_send_timeout 600s;
        proxy_read_timeout 600s;
        proxy_buffering off;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
    

4. 改用异步视图处理下载

Daphne是异步服务器,同步视图可能阻塞事件循环并引发内存异常,改用异步视图配合aiofiles分块读取文件:

import aiofiles
import asyncio
from django.http import StreamingHttpResponse
from django.views import View
from django.utils.decorators import classonlymethod

class BackupDownloadView(View):
    @classonlymethod
    def as_view(cls, **initkwargs):
        view = super().as_view(**initkwargs)
        view._is_coroutine = asyncio.coroutines._is_coroutine
        return view

    async def get(self, request):
        async def file_iterator():
            async with aiofiles.open('/tmp/backup.zip', 'rb') as f:
                while chunk := await f.read(65536):
                    yield chunk

        response = StreamingHttpResponse(file_iterator())
        response['Content-Disposition'] = 'attachment; filename="backup.zip"'
        return response

5. 系统层面优化

  • 增加交换分区:树莓派内存有限,创建2GB交换分区缓解内存压力:
    sudo fallocate -l 2G /swapfile
    sudo chmod 600 /swapfile
    sudo mkswap /swapfile
    sudo swapon /swapfile
    
  • 降低备份任务优先级:用nice命令降低mysqldump和zip的优先级,避免抢占Daphne、MariaDB的资源:
    nice -n 19 mysqldump ... > /tmp/db_backup.sql
    nice -n 19 zip -r /tmp/backup.zip /tmp/db_backup.sql /path/to/other/data
    
  • 优化MariaDB导出参数:添加--quick和--single-transaction减少导出时的内存占用:
    mysqldump --quick --single-transaction -u 用户名 -p密码 数据库名 > /tmp/db_backup.sql
    

6. 排查内存暴增根源

  • 用psutil模块在备份流程关键节点打印内存使用,定位是数据库导出、ZIP打包还是文件响应阶段内存飙升:
    import psutil
    import os
    
    def get_memory_usage():
        process = psutil.Process(os.getpid())
        return process.memory_info().rss / 1024 / 1024  # 单位MB
    
    # 在备份、打包、响应等步骤中调用print(get_memory_usage())
    
  • 确认ZIP文件是直接写入磁盘,而非用BytesIO在内存中生成——这是大文件场景的常见内存泄漏坑。

内容的提问来源于stack exchange,提问作者LudgerH

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 12:46:27