Nginx磁盘空间占用异常问题排查与解决方案记录

发布于:2025-03-02 ⋅ 阅读:(123) ⋅ 点赞:(0)
一、问题描述
  1. 现象
    线上服务器磁盘空间持续被占用,上服务器查询未发现有新增大文件,但是磁盘空间占用还在持续上升。

    • 通过df -hdu -sh对比发现,磁盘占用与实际文件大小不符,存在大量已删除但未释放的文件句柄。
    • 使用lsof | grep delete定位到Nginx进程持有已删除的临时文件(如proxy_temp目录下的文件)。
    • 观察磁盘的io情况,发现nginx的io时速很快,基本在100-300M/s,
      • iotop工具:
    • 尝试回收空间lsof +D   缓存目录
      • sync  #先同步缓存数据
      • echo 1 > /proc/sys/vm/drop_caches:表示清除pagecache。
        echo 2 > /proc/sys/vm/drop_caches:表示清除回收slab分配器中的对象(包括目录项缓存和inode缓存)。slab分配器是内核中管理内存的一种机制,其中很多缓存数据实现都是用的pagecache。
        echo 3 > /proc/sys/vm/drop_caches:表示清除pagecache和slab分配器中的缓存对象。
    • 空间均未释放,后尝试重启Nginx,磁盘空间迅速恢复释放200G。
    • 重启后Nginx占用空间再次迅速上升,未释放进程也快速增加。
    • 怀疑可能是日志问题,查看access.log和error.log均未发现异常。
    • 尝试重启服务器,重启完启动Nginx,磁盘占用问题还是存在。
    • 排查磁盘读写问题:
      • time dd if=/dev/zero of=/data/nginx/data.txt bs=1024k count=10
      • time dd if=/data/nginx/data.txt  of=/dev/null bs=1024k count=10
      • 读写速度均可以达到500M/s以上
      • 排除磁盘问题
  2. 根本原因

    • 确定原因是nginx问题
    • 尝试修改Nginx的配置项
    •  # 设置临时文件目录(支持多级子目录)
          proxy_temp_path /data/nginx/proxy_temp;

        proxy_buffering  off;
       # 可选:限制临时文件最大尺寸(默认1024MB)
      # proxy_max_temp_file_size 50m;

      # client_body_buffer_size  128k;

      #    proxy_buffer_size  8k;

          # 可选:控制单次写入的临时文件大小(默认8KB)
      #    proxy_temp_file_write_size 16k;

          #proxy_buffers 16 64k;          # 缓冲区数量和单缓冲区大小
         # proxy_buffer_size 128k;        # 响应头缓冲区大小
         # proxy_busy_buffers_size 256k;  # 忙碌缓冲区大小

          # 调整临时文件参数
         # proxy_max_temp_file_size 500m;  # 临时文件最大 500MB
         # proxy_temp_file_write_size 512k; # 每次写入 512KB

    • 挨个尝试后,在试到关闭缓存时,发现磁盘占用不上升。修改配置后上线观察。问题初步解决,后续待继续观察。
       


二、排查过程
  1. 定位占用文件

    • 执行命令:
      bash
      lsof | grep '(deleted)'
    • 发现Nginx进程(如PID 4765、4766)持有已删除的临时文件句柄,路径包括/data/nginx/proxy_temp/下的多个文件。
  2. 分析文件类型

    • 通过lsof输出确认,占用空间最大的文件为proxy_temp目录下的临时文件(如00000000520000000059等),大小均超过500MB。
  3. 验证日志影响

    • 检查access.logerror.log,未发现明显异常

三、解决方案
  1. 核心配置调整

    • 关闭proxy_buffering:在Nginx配置中添加proxy_buffering off;,禁止Nginx缓存响应数据到临时文件,直接写入后端服务器。此操作可消除临时文件占用磁盘的问题。

      nginx

      location /api/ {
          proxy_pass http://backend;
          proxy_buffering off;
      }
  2. 辅助优化措施

    • 日志自动轮转
      • 使用logrotate配置日志切割,保留14天历史日志并压缩归档。
      • 示例配置(/etc/logrotate.d/nginx):
        bash
        /var/log/nginx/*.log {
            daily
            rotate 14
            compress
            missingok
            notifempty
            create 640 nginx adm
            sharedscripts
            postrotate
                [ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
            endscript
        }
    • 限制缓存与临时文件空间
      • 配置proxy_temp_pathclient_body_temp_path并设置最大空间(如1GB),避免临时文件无限增长。
      • 配置fastcgi_cache_path限制缓存大小(如2GB)并设置过期时间。
  3. 系统级优化

    • 监控与告警:使用Prometheus + Grafana监控磁盘使用率,设置80%阈值告警。
    • 独立存储日志/缓存:将日志和缓存目录迁移至独立分区或SSD,避免主分区空间不足。

四、实施效果
  • 临时文件释放:关闭proxy_buffering后,Nginx不再生成临时文件,lsof中无(deleted)状态的文件句柄。
  • 日志管理:日志轮转生效,历史日志被压缩归档,磁盘空间占用稳定。
  • 服务稳定性:反向代理请求响应正常,未再出现502错误。

五、总结
  1. 关键结论

    • proxy_buffering off通过禁用Nginx缓存机制,直接写入后端响应,从根本上解决了临时文件占用磁盘的问题。
    • 结合日志轮转、缓存限制和系统监控,可全面保障Nginx的稳定运行。
  2. 后续建议

    • 定期检查Nginx进程的文件句柄使用情况,避免因代码或配置问题导致资源泄漏。
    • 考虑使用Nginx Plus或企业版,其提供更高级的缓存管理和资源监控功能。