这个问题的典型根源在于:客户端上传静态文件(如头像、附件、图片)时,请求被负载均衡(Nginx/HAProxy)分发到了“节点 A”,文件保存在了节点 A 的本地磁盘;当其他请求或刷新页面被分发到“节点 B”时,节点 B 本地根本没有该文件,直接报 404。

引入独立 NFS(网络文件系统) 服务器的作用,就是把多台后端节点的静态资源存储目录,挂载到同一个远程共享存储上,实现“一处写入,多端实时同步可见”。

下面为你完整复现搭建与联调整体流程:

架构拓扑示例

  • NFS 共享存储服务器:192.168.1.100(共享目录 /data/share/static)

  • Web 节点 A:192.168.1.101(挂载点 /var/www/static)

  • Web 节点 B:192.168.1.102(挂载点 /var/www/static)

  • 前端负载均衡(Nginx):分发请求到节点 A 与节点 B

1.配置 NFS 服务端 (192.168.1.100):

首先在专用的 NFS 存储节点上安装服务,并创建数据共享目录:

Bash

# 1. 安装 nfs 核心软件包 (RHEL / CentOS 环境)
sudo dnf install -y nfs-utils rpcbind

# 2. 创建用于集中存放静态资源的目录并赋予权限
sudo mkdir -p /data/share/static
sudo chmod -R 777 /data/share/static

编辑共享导出配置文件 /etc/exports:

Plaintext

/data/share/static 192.168.1.0/24(rw,sync,no_root_squash,no_subtree_check)

参数说明:

  • rw:允许读写权限。

  • sync:同步写入内存与磁盘,保证多节点数据一致性。

  • no_root_squash:允许客户端的 root 用户具有对该目录的 root 级读写权限(若追求更高安全性,可映射为特定应用用户如 nginx 或 nobody)。

启动服务并放行防火墙:

Bash

# 启动并开机自启 rpcbind 与 nfs-server
sudo systemctl enable --now rpcbind nfs-server

# 如果有 firewalld,放行 nfs 相关服务
sudo firewall-cmd --permanent --add-service=nfs
sudo firewall-cmd --permanent --add-service=rpc-bind
sudo firewall-cmd --permanent --add-service=mountd
sudo firewall-cmd --reload

# 确认导出状态
exportfs -rv
showmount -e localhost

2.配置 Web 客户端节点 (节点 A & 节点 B):

在所有承载业务的 Web 节点(如 101、102)上操作,挂载该共享目录:

Bash

# 1. 客户端同样需要安装 nfs-utils 基础组件
sudo dnf install -y nfs-utils

# 2. 检查是否能发现服务端的共享目录
showmount -e 192.168.1.100

# 3. 创建本地挂载目录(对应应用存放静态文件的路径)
sudo mkdir -p /var/www/static

# 4. 手动执行挂载测试
sudo mount -t nfs 192.168.1.100:/data/share/static /var/www/static

验证挂载成功:

Bash

df -h | grep nfs

3.配置开机自动挂载与持久化:避免节点重启后挂载丢失导致静态资源 404。

编辑两个 Web 节点的 /etc/fstab 文件,追加持久化挂载项:

Plaintext

192.168.1.100:/data/share/static  /var/www/static  nfs  defaults,_netdev  0  0

关键注意点: 务必加上 _netdev 参数!它的含义是等待网络服务完全就绪后再进行挂载,防止系统开机过早挂载因网卡未分配 IP 而导致系统启动阻塞。

测试挂载配置是否正确无报错:

Bash

sudo mount -a

4.业务应用与 Nginx 静态路由验证:

1. 目录一致性测试

  • 在节点 A 的 /var/www/static/ 下执行 touch test.jpg。

  • 在节点 B 的 /var/www/static/ 下直接执行 ls,应能立即查看到 test.jpg。

2. Web 站点配置

  • 若节点部署的是 Nginx,配置静态资源路径直接指向该挂载点:

Nginx

location /static/ {
    alias /var/www/static/;
    expires 30d;
    access_log off;
}
  • 客户端无论上传请求被前端负载均衡分发到了节点 A 还是节点 B,写入的其实都是底层的远程 NFS,任何节点均可随时读取,从而彻底解决资源割裂的问题。