documentroot 本身不提供容灾能力,需指向高可用分布式存储挂载点(如 nfs、cephfs、glusterfs 或云 nas),禁止 rsync 同步;须关闭 enablesendfile、fileetag,上传目录应分离至对象存储或专用 nfs,并配合健康检查实现存储级故障感知。

DocumentRoot 本身不直接提供容灾能力,但它可以成为高可用分布式文件系统的“接入点”。关键不是改 DocumentRoot 指令本身,而是让它的物理路径指向一个具备自动故障切换、多节点同步、读写分离能力的共享存储——比如 GlusterFS、CephFS、NFS 高可用集群或云厂商的弹性文件服务(如阿里云 NAS、AWS EFS)。
DocumentRoot 必须指向分布式挂载点
不能把 DocumentRoot 设为本地目录再靠 rsync 同步,那样有延迟、不一致、易出错。正确做法是:在所有 Apache 节点上,将同一套静态资源或 PHP 入口代码挂载到相同路径,然后 DocumentRoot 直接指向该挂载点:
- ✅ 正确:
DocumentRoot "/mnt/nas/example.com/public",且/mnt/nas是通过 NFSv4 或 CephFS mount 的高可用共享卷 - ✅ 正确:
DocumentRoot "/srv/www/example.com",而/srv/www是 GlusterFS 客户端挂载的复制卷(replica 3) - ❌ 错误:各节点用 rsync 推送代码,DocumentRoot 指向各自
/var/www/...—— 故障切换时可能版本不一致、缓存未刷新、上传文件丢失
配套权限与一致性配置不可少
分布式文件系统对 inode、锁、atime/mtime 行为有特殊要求,Apache 必须适配:
支持读取Word文档(.docx/.doc)及中文,可提取文本、搜索关键词并保存为UTF-8文本文件,无需安装Word。
- 挂载时加选项:
nfsvers=4.1,hard,intr,rsize=1048576,wsize=1048576,noatime,nodiratime(NFS);CephFS 建议启用cache=none避免元数据不一致 块中禁用 EnableSendfile Off—— 分布式存储不支持 sendfile 系统调用,否则大文件下载可能卡死或返回空内容- 关闭
FileETag None(尤其配合 mod_expires),因为不同节点读取同一文件的 inode 可能不同,ETag 不一致会导致缓存失效混乱 - PHP 应用若依赖
opcache.file_cache,需指向本地路径(如/tmp/opcache),不能放分布式卷上,否则性能暴跌
上传目录必须单独处理,不能和 DocumentRoot 混用
用户上传的图片、附件等属于动态写入数据,不能直接放在 DocumentRoot 下的分布式卷里——既影响读性能,又带来并发写冲突风险:
- ✅ 推荐:上传目录用独立对象存储(如 MinIO、OSS、S3),前端直传 + 后端签发 token;Apache 仅通过 ProxyPass /uploads/ 转发到对象网关
- ✅ 次选:上传目录走专用高可用 NFS 卷,但 DocumentRoot 保持只读,
/uploads用 Alias 映射并单独配,且禁止执行权限( Options -ExecCGI -Includes) - ❌ 避免:把
/var/www/example.com/uploads和代码一起挂分布式卷 —— 多节点同时写一个目录,极大概率损坏文件或覆盖内容
健康检查与故障感知要联动
光挂载成功不够,Apache 需感知后端存储是否可用,避免返回 500 或空白页:
- 在
中用 CheckSpelling off和AcceptPathInfo off减少因路径解析异常引发的误判 - 配合外部探针(如 curl -f http://localhost/health/storage)定期检测挂载点下某个测试文件可读性,失败则触发告警或自动切流
- 负载均衡器(如 Nginx、HAProxy)不应只检查 Apache 进程端口,还要结合存储健康状态做综合判断——例如 HAProxy 的
http-check expect status 200指向一个读取分布式卷小文件的 PHP 脚本










