ngx_http_slice_module仅实现请求级Range切片而非文件物理分片,需与proxy_cache等协同实现按需缓存;配置中必须用$slice_range构造cache_key以隔离不同分片缓存,源站须稳定支持206响应。

ngx_http_slice_module 本身不负责“分片存储”,它只做请求切片(即把一个大文件的 HTTP 请求拆成多个小范围请求),用于配合后端源站支持 Range 的场景,从而降低回源压力、提升缓存效率和客户端首屏体验。真正实现“分片存储 + 按需分发”,需要它与 proxy_cache、proxy_cache_use_stale、proxy_cache_lock 等机制协同工作。下面从原理到配置讲清楚关键点。
理解 slice 模块的核心作用:按 Range 切割请求,而非切割文件
该模块不会把一个 10GB 的文件物理拆成多个小文件存到磁盘;它只是在 Nginx 接收客户端对 /video.mp4 的完整请求时,根据 slice 指令将这个请求转换为多个带 Range: bytes=0-1048575、Range: bytes=1048576-2097151 等头的子请求,发往上游源站。每个子请求返回对应片段,Nginx 再拼装响应给客户端。
这意味着:
- 源站必须支持标准
Range请求并返回206 Partial Content - Nginx 自身不保存“分片文件”,但可利用 proxy_cache 缓存每个 Range 响应(以 URI + Range 头为 key)
- 后续相同 Range 的请求可直接命中缓存,无需再次回源
启用 slice + cache 实现“逻辑分片缓存”
要让 Nginx 对大文件做到“按需拉取、按需缓存、按需返回”,需组合以下配置:
注意:cache_key 必须包含 $slice_range,否则所有 Range 请求都缓存到同一个 key 下,导致内容错乱。
proxy_cache_path /data/cache slices levels=1:2 keys_zone=slice_cache:100m max_size=10g inactive=3d use_temp_path=off;
<p>server {
listen 80;
location /video/ {</p><h1>启用 slice,每片 1M</h1><pre class="brush:php;toolbar:false;"> slice 1m;
# 代理到源站
proxy_pass https://origin.example.com;
# 关键:为每个 Range 构建独立 cache key
proxy_cache slice_cache;
proxy_cache_key "$scheme$host$request_uri$slice_range";
proxy_cache_valid 200 206 1h;
# 允许并发回源时只让第一个请求穿透,其余等待(避免雪崩)
proxy_cache_lock on;
proxy_cache_lock_timeout 3s;
# 即使缓存过期,也允许 stale 状态下响应 Range(提升可用性)
proxy_cache_use_stale http_500 http_502 http_503 http_504 updating error timeout;
# 强制要求上游支持 Range,并透传相关头
proxy_set_header Range $slice_range;
proxy_ignore_headers Cache-Control Expires Set-Cookie;
add_header X-Slice-Range $slice_range;
}}
实际效果与典型行为
假设用户请求 GET /video/movie.mp4(无 Range):
- Nginx 不会直接转发,而是触发 slice,发起多个子请求:
Range: bytes=0-1048575、bytes=1048576-2097151… - 每个子请求被缓存为独立条目(key 包含 $slice_range),例如:
http://example.com/video/movie.mp4bytes=0-1048575 - 当另一个用户请求同一文件的第 3 片(如播放器 seek 到中间),Nginx 直接从缓存返回该 Range,不回源
- 若某一片缓存失效,仅该片回源,不影响其他已缓存分片
这种机制天然适配视频点播、大安装包下载等场景,尤其利于 HLS/DASH 的 .ts/.mp4 分片播放逻辑。
注意事项与常见坑
- 源站必须稳定支持 Range:部分源站(尤其自研服务)可能忽略 Range 或返回 200 全量内容,需严格测试
- 不要混用 slice 和 proxy_buffering off:关闭 buffer 可能导致 slice 无法正确组装响应,建议保持默认开启
- cache key 中不能漏掉 $slice_range:这是最关键的缓存隔离条件,漏掉会导致不同分片相互覆盖
- slice 大小需权衡:太小(如 64k)增加请求次数和 header 开销;太大(如 10m)降低缓存粒度和首片加载速度,1–2MB 是较优选择
-
不适用于非 Range 场景:如果客户端始终发完整 GET 请求(无 Range),slice 模块不会生效,此时应考虑用
proxy_buffering+proxy_max_temp_file_size控制内存/临时文件使用

















