nginx中对大文件启用directio可绕过内核页缓存,降低内存压力并提升i/o效率;需配合aio threads、thread_pool、directio_alignment及sendfile off四者协同生效。

在 Nginx 中对大文件启用 directio,核心目标是绕过内核页缓存(page cache),避免把大量文件内容“吃进”内存缓存,从而防止挤占其他服务或小文件的缓存空间。这不是简单地“关掉缓存”,而是让读取路径更轻量、更可控——尤其适合视频、安装包、镜像等 ≥5MB 的静态资源。
directio 的作用与适用场景
directio 让 Nginx 以 O_DIRECT 方式读取文件:数据不经过内核缓冲区,直接从磁盘搬入用户空间缓冲区再发给客户端。它省掉了“磁盘→内核页缓存→用户空间”的二次拷贝,降低内存压力,也避免大文件污染 page cache,影响系统整体 I/O 效率。
注意:它只对大文件有效,且和 sendfile 互斥;小文件用 directio 反而性能下降,因为缺失页缓存命中优势。
基础配置写法(location 级别)
推荐按文件类型或路径区分启用,例如专用于下载目录:
location /download/ {
alias /data/files/;
directio 5m; # 文件 ≥5MB 时启用 directio
aio threads; # 必须配合异步 I/O,否则会阻塞
output_buffers 1 128k; # 减少小块写次数,提升吞吐
sendfile off; # 与 directio 冲突,必须关闭
}
-
directio 5m表示文件大小 ≥5MB 才走直接读;小于该值仍走常规路径(可命中 page cache) -
aio threads是关键:没有它,directio 会退化为同步阻塞读,拖慢 worker 进程 -
output_buffers控制发送缓冲,避免高频小 write() 系统调用,适配大文件流式响应
配套必须项:thread_pool 与 aio threads
仅写 aio threads 不够,主线程池必须提前定义并绑定到缓存路径(如果用了 proxy_cache)或确保全局可用:
# 在 http 或 main 块顶部定义线程池 thread_pool default threads=16 max_queue=4096; <h1>若启用了代理缓存,proxy_cache_path 需显式绑定</h1><p>proxy_cache_path /data/cache levels=1:2 keys_zone=mycache:100m use_temp_path=off thread_pool=default;</p>
- 线程数建议设为 CPU 核心数 × 2~4,max_queue 要足够容纳并发读请求,避免排队超时
- 若未用 proxy_cache,仅做静态文件服务,
thread_pool定义后,aio threads即可生效 - 务必确认文件系统支持 O_DIRECT(ext4/xfs 均支持,但需对齐;见下条)
对齐要求与文件系统适配
使用 directio 时,Nginx 默认按 512 字节对齐读取;但某些文件系统(如 XFS)或 SSD 设备更倾向 4KB 对齐,否则可能触发内核回退到普通 IO:
- 添加
directio_alignment 4k;到同级配置块(http/server/location) - 确保后端存储挂载时开启
noatime,nodiratime,减少元数据写入干扰 - 验证是否真正生效:用
strace -p $(pgrep nginx) -e trace=io_submit,read观察是否出现io_submit调用
不复杂但容易忽略:directio 不是开个开关就完事,它需要 aio + thread_pool + 对齐 + sendfile 关闭四者协同,才能真正把大文件读操作“卸载”出主线程,既保性能又护内存。











