必须在main块定义thread_pool并绑定proxy_cache_path,启用aio threads且关闭sendfile,配合directio和output_buffers才能高效异步读取大文件缓存。

要让 Nginx 在代理缓存场景下高效读取大文件(如视频、安装包等),不能只靠默认的同步读取——它会阻塞 worker 进程,拖慢整体吞吐。启用固定线程池(thread_pool)配合异步 I/O(aio threads),才能把磁盘读操作从主线程剥离,释放 worker 处理更多连接。
声明并命名一个专用线程池
线程池必须在 main 块中全局定义,不能放在 http 或 location 内。建议为大文件缓存单独起名(如 cache_pool),便于隔离和监控:
thread_pool cache_pool threads=16 max_queue=4096;-
threads=16:适配常见 SSD 的并发读能力,避免过多线程争抢队列;若 CPU 核心多于 16,可按 1:1 或 2:1(核数:线程数)微调 -
max_queue=4096:防止请求堆积溢出;低于默认 65536 是因代理缓存读通常比静态服务更可控,过大的队列反而增加延迟
在 proxy_cache_path 中启用线程池读取
Nginx 1.17.6+ 支持为缓存路径指定线程池,这是关键一步。需在 proxy_cache_path 指令中显式绑定:
proxy_cache_path /var/cache/nginx/proxy levels=1:2 keys_zone=cache_zone:100m inactive=60m use_temp_path=off thread_pool=cache_pool;-
use_temp_path=off必须开启:强制所有缓存写入主路径(而非临时目录),确保线程池能统一调度读操作 - 路径
/var/cache/nginx/proxy应挂载在 SSD 上,且所在文件系统(推荐 XFS)需支持 direct I/O 和异步操作
在 location 中启用异步读 + 禁用 sendfile
仅配置线程池还不够,需配合具体的 I/O 模式切换:
-
aio threads;—— 启用线程池异步读(不是aio on,后者依赖内核 AIO,兼容性差) -
directio 10m;—— 对 ≥10MB 的缓存文件启用 direct I/O,绕过页缓存,减少内存拷贝,尤其适合大文件连续读 -
sendfile off;—— 必须关闭:因为sendfile与aio threads冲突,Nginx 无法将 direct I/O 和零拷贝同时用于同一响应 -
output_buffers 2 128k;—— 配合异步读,为发送阶段预留缓冲,避免频繁小块写
验证与调优要点
上线后需确认线程池真正生效,并避免反效果:
- 用
ps -eT | grep nginx | wc -l查看实际线程数,应接近worker_processes × threads(如 4 worker × 16 = 64) - 观察
iostat -x 1:若%util接近 100% 但await仍高,说明线程数不足或 SSD 队列深度未打满;可尝试提升threads或检查 NVMe 的nr_requests - 禁止在同一个 location 同时开启
gzip on和大文件线程池读——压缩会强制全量读入内存,抵消异步优势;大文件应单独路由并禁用压缩 - 注意日志级别:
error_log /var/log/nginx/error.log info;可捕获aio相关警告(如线程池满、fallback 到 sync)


















