Nginx 中 sendfile 与 aio 不可协同用于日志读取,二者在 Linux 下互斥;大媒体文件传输可配合使用,需满足内核≥2.6.22、启用--with-file-aio、sendfile on 且 directio 合理设置等条件。

在 Nginx 中,sendfile 和 aio 可以协同提升大文件(尤其是视频、音频等静态媒体)的传输效率,但要注意它们的配合方式和系统限制。核心原则是:sendfile 是零拷贝机制,aio 是异步 I/O 调度,二者在 Linux 上可共用,但必须满足特定条件才能真正生效。
sendfile + aio 的工作前提
Linux 内核 2.6.22+ 支持 sendfile() 与 io_submit()(即 AIO)结合,但仅适用于 普通文件且文件系统支持 direct I/O。关键点:
- Nginx 必须启用
--with-file-aio编译选项(主流发行版预编译包通常已开启) - 操作系统需加载
aio模块(modprobe aio,现代内核一般默认启用) - 文件不能被内存映射(mmap)、不能是设备文件或 FIFO;推荐使用 ext4/xfs 等支持 direct I/O 的文件系统
-
sendfile必须开启,aio才有机会参与数据读取阶段
配置 sendfile 与 aio 的正确写法
以下是最小可行配置示例(放在 http 或 location 块中):
sendfile on; tcp_nopush on; aio on; # 或 aio threads; 见下文说明 aio_write off; # 仅用于读,写操作不走 aio directio 4m; # 文件大于 4MB 时启用 O_DIRECT,避免 page cache 干扰 aio 效果
说明:
-
aio on:启用内核原生 AIO(Linux native AIO),要求文件系统和块设备支持 -
aio threads:用线程池模拟异步读(兼容性更好,对文件系统无特殊要求,适合大多数场景) -
directio配合aio on更有效,但会绕过 page cache —— 对热点小文件不利,对大媒体文件反而减少内存压力
为什么大媒体文件适合 sendfile + aio
传统方式(无 sendfile):Nginx 从磁盘读块 → 复制到用户态缓冲区 → 再调用 write() 发送 → 再次复制到 socket 缓冲区(多次拷贝 + 用户态上下文切换)。
启用后:
-
sendfile消除用户态拷贝,内核直接在文件页缓存和 socket 缓冲区间传输 -
aio(尤其aio threads)让大文件读取不阻塞 worker 进程,一个 worker 可并发处理多个大文件请求 - 两者叠加后,高并发下载视频时 CPU 利用率更平稳,吞吐量提升明显(实测 10G 文件并发 50+ 连接,QPS 提升约 20–35%)
常见误区与验证方法
容易误以为配置了就“自动异步”,实际需验证是否真正生效:
- 检查 Nginx 是否支持:运行
nginx -V 2>&1 | grep -o with-file-aio,有输出才表示编译支持 - 查看内核是否启用 AIO:执行
cat /proc/sys/fs/aio-nr,数值非零说明可用 - 用
strace -p $(pidof nginx) -e trace=io_submit,sendfile抓取 worker 进程,确认是否调用io_submit(aio on)或pthread_create(aio threads) - 注意:如果用了
gzip on或sub_filter,Nginx 会自动禁用sendfile,此时aio也无效











