apache启用sendfile后,数据全程在内核空间传输,省去两次用户态参与和两次内存拷贝,上下文切换减半、cpu负载显著下降。

Apache 处理大流量静态文件时,CPU 上下文切换开销主要来自传统 read/write 路径:每次请求都要在用户态与内核态之间来回切换两次(read 进入内核、write 再进内核),同时搬运数据四次。启用 sendfile 后,数据全程留在内核空间完成磁盘文件到 socket 的直接传输,省掉两次用户态参与和两次内存拷贝,上下文切换次数减半,CPU 负载显著下降。
确认并启用 Sendfile 功能
Apache 2.0+ 默认内置 sendfile 支持,无需额外加载模块。只需检查配置中是否开启:
- 确保 EnableSendfile on 已设置(多数发行版默认开启,但容器镜像或加固系统可能关闭)
- 无需启用 mod_sendfile —— 它不是独立模块,而是 Apache core 的一部分
- 重启后用 httpd -M | grep sendfile 验证无报错即可,不需单独列出
让 Sendfile 真正生效的关键条件
Apache 很谨慎,只要检测到以下任一情况,就会自动退回到 read/write 模式,sendfile 形同虚设:
Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
- 响应被任何模块修改元信息:如 mod_headers 重写了 Last-Modified 或 ETag
- 文件不在本地文件系统:NFS、CIFS、FUSE 或某些网络存储挂载点通常不支持 sendfile 接口
- 客户端使用 HTTP/1.0 且未声明 Connection: keep-alive,导致连接无法复用 page cache
- 启用了 mod_deflate 或 mod_php 等内容处理模块——压缩或执行脚本必然经过用户态,sendfile 被强制禁用
- 文件大小超过 SendfileMaxSize 限制(旧版默认 2GB,新版通常不限)
验证运行时是否真走 sendfile 路径
不能只看配置,必须抓取真实请求的系统调用行为:
- 用 strace -p $(pgrep apache2 | head -1) -e trace=sendfile64,read,write -f 监控一个静态资源请求(如 /test.zip)
- 若看到 sendfile64( 调用且无对应 read/write,说明生效
- 若只看到大量 read()/write(),说明已被降级——此时应排查上述失效条件,而非调优缓冲区或 MPM
配套优化提升 sendfile 效果
sendfile 不是孤立开关,需配合其他设置才能发挥最大价值:
- 禁用无关模块:移除 mod_deflate、mod_headers(除非必要)、mod_php;改用 proxy_fcgi + PHP-FPM 分离动态逻辑
- 静态资源分离部署:将 mp4、zip、iso 等大文件放在专用 location 块中,避免与其他规则混用
- 保持 Content-Length 准确:确保文件未被截断、未启用 EnableMMAP off(影响 mmap 失败后 fallback 行为)
- 搭配 KeepAlive 合理设置:KeepAliveTimeout 设为 2–3 秒,既复用连接降低 accept/close 开销,又避免长空闲占用线程










