关键在于协同调优slice分片、proxy_cache缓存及sendfile/aio/directio等I/O配置:slice设512k–2m,缓存键含$slice_range,启用proxy_cache_lock,配合sendfile与aio+directio减少拷贝和落盘。

要让 Nginx 的 slice 模块在大文件分发中既不压垮磁盘 I/O,又不浪费带宽,关键不是“开开关关”,而是把分片逻辑、缓存策略和底层 I/O 行为串起来调。
slice 大小要匹配后端响应特性
切片不是越小越好,也不是越大越稳——它得贴合源站能力与网络延迟:
- 设为 512k–2m 是多数场景的起点:太小(如 128k)会让一次下载触发几十甚至上百个子请求,放大后端并发压力和磁盘随机读;太大(如 8m)则单次 206 响应体过大,易触发临时文件写入或缓冲区溢出
- 若后端是对象存储(OSS/S3),确认其 Range 响应首字节延迟是否稳定;延迟高时,适当增大 slice 值可减少请求数,降低连接建立开销
- 最后一片永远不固定,Nginx 自动计算;无需手动处理,但要注意监控
200回退情况——这说明某次子请求没带 Range 或源站拒绝了
必须配缓存,否则 slice 反而加重 I/O
slice 本身不缓存,全靠 proxy_cache 把每个分片响应存住。没缓存的 slice 就是“多线程反复打源站”:
- 缓存键一定要包含
$slice_range:
proxy_cache_key "$scheme$request_method$host$uri$is_args$args$slice_range"; - 声明双状态有效期:
proxy_cache_valid 200 206 1h; ——200 是整文件兜底,206 是分片主体 - 开启
proxy_cache_lock on,防止相同分片的并发请求穿透到后端,避免重复读盘 - 缓存路径建议挂 SSD,且
proxy_temp_path与proxy_cache_path分开,避免临时文件争抢空间
协同底层 I/O 配置,减少内核拷贝与落盘
slice 分片响应最终要从磁盘/内存送到客户端,这时 sendfile、aio、directio 就得配合上:
- 保持
sendfile on,这是零拷贝基础;slice 场景下,它负责把缓存好的分片内容高效送出去 - 如果后端响应体大(比如单个 206 超过 4MB),启用
aio on+directio 4m,跳过页缓存,减少内存拷贝和脏页回写压力 - 注意
directio仅对 ≥ 阈值的文件生效,且要求文件系统支持(XFS 推荐,ext4 需确认挂载选项不含nobarrier) - 禁用
proxy_buffering off不适用于 slice 场景——它只适合流式后端;slice 必须依赖 buffering 来组装各分片响应头与体
监控与验证要点
调优后不能只看下载速度,要盯住三个层面是否真正解耦:
- 查 Nginx 日志:
status=206占比应 >95%,status=200多说明源站 Range 不稳定 - 看磁盘指标:
iotop -a观察nginx: worker process的 IO_WAIT 和实际读写量,若持续高 IO_WAIT,可能是 slice 过小或缓存未命中 - 用
curl -i -H "Range: bytes=0-1048575" http://x/download/big.zip手动测单片响应,确认返回含Content-Range: bytes 0-1048575/123456789且无Transfer-Encoding: chunked











