一、为什么需要 Slice?
在 NGINX 反向代理或 CDN 场景中,大文件(视频、软件包、镜像等)常因单体体积过大而令缓存命中率低、回源代价高。
ngx_http_slice_module
通过把一次完整响应拆分成 固定大小的字节块(Slice),让各块分别缓存,从而带来三大收益:
更高缓存命中率
- 客户端断点续传、并发 Range 请求只命中需要的分片,无须整文件回源。
回源压力小
- 回源服务器可串流输出,对下游节点按块供给,避免一次性读取整文件。
快速失败与热区
- 若分片出现损坏或更新,仅重拉对应 Slice,其他分片继续复用缓存。
二、模块启用
ngx_http_slice_module
默认未编译。必须在编译 NGINX 时加入:./configure --with-http_slice_module \ --with-http_ssl_module # 其他模块 make && sudo make install
验证是否编译成功:
nginx -V 2>&1 | grep --color http_slice
三、核心概念
名称 | 说明 |
---|---|
Slice | 一个固定大小的字节块(例如 1 MiB),每个块通过子请求(subrequest)回源并缓存。 |
$slice_range |
模块自动生成的变量,格式形如 bytes=0-1048575 ,指明本子请求需要的区间;需作为 Range 头传递给上游。 |
状态码 206 | 分片请求回源时,上游需返回 206 Partial Content 并带 Content-Range ,NGINX 缓存到本地。 |
子请求 (subrequest) | NGINX 在后台对每个 Slice 发起独立请求;与 proxy_cache_background_update 等子请求并存时有已知问题(见后文)。 |
四、最小可用配置(一步一步)
假设:
- 回源服务
http://localhost:8000/
存放大文件; - 目标:把每个响应切成 1 MiB 切片并缓存。
http {
proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=cache:100m inactive=1h;
server {
listen 80;
location / {
# 1. 开启分片,单位可用 k/m/g
slice 1m;
# 2. 启用缓存
proxy_cache cache;
proxy_cache_valid 200 206 1h;
# 3. 把分片区间加入缓存 key,保证不同片段独立缓存
proxy_cache_key $uri$is_args$args$slice_range;
# 4. 告诉回源取哪段字节
proxy_set_header Range $slice_range;
# 5. 回源
proxy_pass http://localhost:8000;
}
}
}
流程说明:
- 首个请求 → NGINX 判断需切片,先取
slice=0~1048575
。 - cache miss → 向回源带
Range: bytes=0-1048575
,获得206
,缓存。 - 后续切片 → 继续子请求;未命中则回源、命中则直返。
- 客户端端网速变化 → 支持断点续传;若断线后重连,只拉缺失部分,命中率高。
五、可调指令
5.1 slice size;
size:每片大小,可写
256k | 1m | 4m
等;0(默认)关闭切片。
建议:
- 小文件 < size -> 不切片;
- 过小会导致文件句柄过多,过大会降低命中率,常用 512 k ~ 2 m。
5.2 $slice_range
无需显式定义,模块自动按 slice
和当前偏移生成。例如:
bytes=1048576-2097151
务必用 proxy_set_header Range $slice_range
传递给上游。
六、进阶技巧
6.1 HTTPS 回源 + Range
若回源是 HTTPS,上游同样须支持分段下载;否则 NGINX 会回退整文件。
proxy_pass https://backend.example.com;
proxy_set_header Range $slice_range;
6.2 限制并发子请求
过多并发会给回源带来压力,可在 proxy_cache_lock
/ limit_conn
等模块配合限流。
proxy_cache_lock on; # 只有首个分片回源,其余等待,防止击穿
limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn perip 10; # 每 IP 最多 10 并发
6.3 与 Range/Head 兼容
客户端自己发 Range(断点续传)时,Slice 会在原有 Range 内继续切分,返回多片合并结果,对客户端透明。
6.4 NJS 动态调整 Slice
可用 set $slice_size ...
+ slice $slice_size;
按不同 URI / MIME 策略动态调整分片大小。
七、已知问题与避坑
场景 | 问题表现 | 解决建议 |
---|---|---|
Background Cache Update | 使用 proxy_cache_background_update on; 时,不支持 Range,可能整文件回源 |
避免在同一 location 打开该特性;或使用主动刷新脚本 |
过小 Slice (<32k ) |
fd 数暴增、内存占用高 | Slice ≥ 256k;确保 worker_rlimit_nofile 足够 |
回源不支持 Range | 上游返回 200 整文件,Slice 无意义 | 确认回源支持 Accept-Ranges: bytes headers |
ETag 变化 | 不同分片用不同 ETag 导致缓存击穿 |
统一回源 ETag 或禁用 proxy_ignore_headers ETag; |
八、监控 & 调试
- 查看缓存:
ls -l /data/nginx/cache
,每片生成独立缓存文件。 - 日志标记:在
log_format
中加入$slice_range
、$upstream_status
便于排查:
log_format slice '$remote_addr $uri $status '
'range=$slice_range up=$upstream_status';
access_log /var/log/nginx/slice.log slice;
性能指标:
proxy_cache_hit
,miss
connections_active
,reading
,writing
- 磁盘 IO
九、场景实战
9.1 大文件下载(ISO、固件)
slice 2m; # 较大分片减少文件数
proxy_cache_valid 200 206 12h; # 长时间缓存
9.2 HLS/DASH 点播
分片文件本就小,可关闭切片,或仅对 .mp4
大文件切片:
location ~ \.mp4$ {
slice 1m;
...
}
9.3 镜像仓库代理
镜像层 (layer) 可达数百 MB,开启切片后可极大提高复用率。
十、总结
一句话:
ngx_http_slice_module
通过“分片 + 缓存”让大文件交付更高效。必做:
- 编译开启
--with-http_slice_module
- 设置
slice
大小 + 缓存 key 中加入$slice_range
- 将
$slice_range
作为Range
头传递 - 缓存中允许状态码
206
- 编译开启
可选:结合
proxy_cache_lock
、limit_conn
、自定义session_log
等做进一步优化。
掌握上述配置与注意事项后,你就可以让 NGINX 在大文件分发、CDN 边缘缓存、镜像仓库等场景下发挥极致性能,显著降低回源压力与带宽消耗。祝你使用顺利,缓存命中率节节攀升!