一、项目背景
1.1 业务场景与核心需求
在企业数字化转型进程中,Web 服务作为业务对外交付的核心载体,其高可用性、高并发承载能力、数据一致性是保障业务稳定运行的关键要素。以电商平台、企业官网、在线教育等典型场景为例,需满足以下核心诉求:
- 高可用保障:Web 服务需实现 7×24 小时不间断运行,规避服务器宕机、网络中断等单点故障引发的业务中断问题;尤其在促销、峰值访问时段,服务不可用将直接造成经济损失或用户流失。
- 高并发承载:面对日均 PV 从 10 万级向百万级增长的访问量,单台 Web 服务器的 CPU、内存、网络带宽易形成性能瓶颈;需通过负载均衡分摊请求压力,确保 95% 的请求响应时间<1 秒。
- 数据一致性:Web 服务涉及的静态资源(HTML、CSS、图片、视频)与动态业务数据(用户上传文件、订单记录),需在多台 Web 服务器间共享,避免 "不同服务器展示内容不一致" 的业务异常。
- 易维护与扩展性:业务增长过程中,需支持快速新增 Web 节点以扩展集群能力,同时降低运维复杂度,避免重复部署资源、手动同步配置的低效操作。
1.2 传统架构的痛点与局限
在采用「Keepalived + LVS (DR) + Nginx + NFS」方案前,多数企业采用 "单 Web 服务器" 或 "简单负载均衡" 架构,存在以下难以解决的问题:
1.2.1 单点故障风险高
- 传统 "单台 Nginx 服务器 + 本地存储" 架构中,服务器硬件故障(硬盘损坏、电源故障)或软件异常(Nginx 进程崩溃)会直接导致服务完全不可用;MTTR(平均恢复时间)依赖人工干预,通常超过 30 分钟,无法满足业务连续性要求。
- 即便采用 "2 台 Nginx 服务器 + 简单 DNS 轮询",若其中一台服务器宕机,DNS 缓存会导致部分用户仍被解析至故障节点;且 DNS 轮询无法感知服务器负载状态,易出现 "故障节点持续接收请求" 或 "高负载节点被分配更多请求" 的问题。
1.2.2 并发承载能力不足
- 单台 Nginx 服务器受限于 CPU 核心数(如 4 核 8G 服务器仅能稳定承载 2000-3000 并发连接),访问量峰值超过阈值时,会出现请求排队、页面超时、503 错误等问题。
- 仅通过 "增加服务器数量" 扩展时,缺乏高效的负载均衡机制,无法将请求合理分配至各节点,导致资源浪费(部分服务器空闲)与性能瓶颈(部分服务器过载)并存。
1.2.3 数据共享与一致性难题
- 多台 Nginx 服务器采用 "本地存储静态资源" 时,需通过 rsync 等脚本定期同步资源,但同步延迟易导致 "用户访问不同节点看到不同版本内容"(如首页图片更新后,部分节点仍展示旧图)。
- 动态数据(用户上传的头像、订单附件)若存储在本地,无法在多节点间共享,引发 "用户在 A 节点上传文件后,切换至 B 节点无法查看" 的业务异常。
1.2.4 运维效率低下
- 每台 Web 服务器需单独部署 Nginx 配置、静态资源、业务代码,新增节点时运维人员需重复操作,耗时且易出错(如配置文件漏改、资源版本不一致)。
- 缺乏统一的资源管理机制,静态资源更新(如 CSS 样式调整、图片替换)时需逐台服务器修改,运维成本随节点数量增加呈线性上升。
1.3 技术方案的选型逻辑
针对上述痛点,需构建 "高可用负载均衡 + 共享存储 + Web 服务集群" 一体化架构,「Keepalived + LVS (DR) + Nginx + NFS」组合的选型逻辑如下:
1.3.1 解决高可用与负载均衡
- LVS(Direct Routing 模式)作为四层负载均衡器,具备超高并发承载能力(单机可支撑 10 万 + 并发连接);DR 模式避免 "请求回程流量" 占用带宽,保障转发效率。
- Keepalived 通过 VRRP 协议实现 LVS 主备高可用,主节点故障时,备节点可在 1-3 秒内自动接管虚拟 IP(VIP),实现 "无感知切换",彻底消除负载均衡层单点故障。
1.3.2 保障 Web 服务稳定性
- Nginx 作为成熟的 Web 服务器,兼容性强、配置灵活,可稳定运行 PHP、Python 等动态业务代码;同时通过 mod_cache、mod_gzip 等模块优化静态资源访问性能。
- 多台 Nginx 组成集群,通过 LVS 分摊请求压力;单节点故障时,LVS 自动将请求转发至其他健康节点,保障服务连续性。
1.3.3 实现数据一致性与共享
- NFS(网络文件系统)作为共享存储,将所有 Web 服务器的静态资源目录(/images、/css)与动态上传目录(/uploads)挂载至 NFS 服务器,实现 "多节点访问同一存储资源",彻底解决数据同步问题。
- NFS 支持权限控制与读写分离(可选配置),可保障资源访问安全性与存储性能。
1.3.4 降低运维复杂度
- 架构模块化设计,各组件职责清晰(LVS 负责转发、Nginx 负责服务、NFS 负责存储),便于故障定位与单独扩展。
- 新增 Web 节点时,仅需安装 Nginx 并挂载 NFS 目录,无需重复部署资源,运维效率提升 80% 以上。
1.4 项目价值与预期目标
部署「Keepalived + LVS (DR) + Nginx + NFS」架构后,预期实现以下业务与技术价值:
- 业务连续性:Web 服务可用性从 99.9% 提升至 99.99%(年均停机时间从 8.76 小时降至 52.56 分钟),核心业务场景(电商促销、在线考试)无服务中断风险。
- 性能提升:并发承载能力从单台服务器 3000 并发提升至集群 10 万 + 并发,页面响应时间稳定在 500ms 以内,用户体验显著优化。
- 运维效率:资源部署与更新效率提升 80%,新增节点时间从 2 小时缩短至 15 分钟,减少重复人工操作。
- 扩展性:支持 Web 节点与 NFS 存储独立扩展(如新增 Nginx 节点提升并发、扩容 NFS 存储容量),满足业务 3-5 年增长需求。
二、项目实践
2.1 项目环境

| 主机名 | net1 | net8 | net2 | VIP | 服务器角色 |
|---|---|---|---|---|---|
| client2 | 10.1.1.21 | 外部客户端 | |||
| router | 10.1.1.20 | 10.1.8.20 | 10.1.2.20 | 出口路由器 | |
| client1 | 10.1.8.21 | 内部客户端 | |||
| web1 | 10.1.8.11 | 10.1.2.11 | 10.1.8.100 | Web 服务器 | |
| web2 | 10.1.8.12 | 10.1.2.12 | 10.1.8.100 | Web 服务器 | |
| web3 | 10.1.8.13 | 10.1.2.13 | 10.1.8.100 | Web 服务器 | |
| ha1 | 10.1.8.14 | 10.1.8.100 | HA 和 LVS 服务器 | ||
| ha2 | 10.1.8.15 | 10.1.8.100 | HA 和 LVS 服务器 | ||
| nfs | 10.1.2.100 | 存储服务器 |
网络说明
-
所有主机网卡命名规则:第一块网卡为 ens32,第二块为 ens33,第三块为 ens34(注:原文笔误 "第二块网卡名为 ens34",已修正表述)。
-
网卡模式:默认第一块网卡为 NAT 模式,第二块为 Host-Only 模式。
-
网关配置规则:
- 10.1.1.0/24 网段网关为 10.1.1.20;
- 10.1.2.0/24 网段网关为 10.1.2.20;
- 10.1.8.0/24 网段网关为 10.1.8.20;
- 路由器自身网关为 10.1.8.2。
2.2 基础配置
基础配置包含主机名、IP 地址、网关的标准化配置,以下为网关配置的参考命令(需根据不同网段适配):
bash
## 10.1.1.0/24 网段网关配置(适配对应网卡)
nmcli connection modify ens33 ipv4.gateway 10.1.1.20
nmcli connection up ens33
## 10.1.2.0/24 网段网关配置(适配对应网卡)
nmcli connection modify ens33 ipv4.gateway 10.1.2.20
nmcli connection up ens33
## 10.1.8.0/24 网段网关配置(适配对应网卡)
nmcli connection modify ens33 ipv4.gateway 10.1.8.20
nmcli connection up ens33
2.3 路由器(router)配置
路由器核心作用是开启 IP 转发与防火墙伪装,保障跨网段通信正常:
bash
## 开启IP转发功能(永久生效)
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
## 备选方案:修改现有配置项
# sed -i "s/ip_forward=0/ip_forward=1/g" /etc/sysctl.conf
sysctl -p # 加载配置生效
# 启动防火墙并开启地址伪装(保障NAT转发)
systemctl enable firewalld.service --now
firewall-cmd --add-masquerade # 临时生效
firewall-cmd --add-masquerade --permanent # 永久生效
配置免密登录-(参考)
bash
[root@client ~]#
# 关闭SSH主机密钥检查(避免交互提示)
echo 'StrictHostKeyChecking no' >> /etc/ssh/ssh_config
# 生成RSA密钥对(无密码)
ssh-keygen -t rsa -f .ssh/id_rsa -N ''
# 批量分发公钥至目标节点(需替换server列表为实际主机名)
for host in server server{1..5}; do ssh-copy-id root@$host; done
# 同步SSH配置至目标节点
for host in server server{1..5}; do scp /etc/ssh/ssh_config root@$host:/etc/ssh/ssh_config; done
# 验证免密登录(执行hostname命令)
for host in server server{1..5}; do ssh root@$host hostname; done
## 同步/etc/hosts文件(统一主机名解析)
for host in server server{1..5}; do scp /etc/hosts root@$host:/etc/hosts; done
2.5 NFS 服务器配置
NFS 服务器用于提供共享存储,保障所有 Web 节点资源一致性,操作步骤如下:
bash
## 安装NFS服务依赖包
[root@nfs ~ 10:52:45]# yum install -y nfs-utils
## 准备共享目录与测试文件
[root@nfs ~ 11:37:01]# mkdir /usr/share/nginx/html -p # 创建Nginx默认站点目录
[root@nfs ~ 11:37:16]# echo Welcome to www.liu.cloud > /usr/share/nginx/html/index.html # 写入测试内容
## 配置NFS共享规则(仅允许10.1.2.0/24网段读写、同步访问)
[root@nfs ~ 11:37:27]# echo '/usr/share/nginx/html 10.1.2.0/24(rw,sync)' >> /etc/exports
## 启用并启动NFS服务
[root@nfs ~ 11:37:40]# systemctl enable nfs-server.service --now
Created symlink from /etc/systemd/system/multi-user.target.wants/nfs-server.service to /usr/lib/systemd/system/nfs-service
2.6 Web 节点(web1/web2/web3)基础配置
Web 节点核心部署 Nginx 服务,先完成基础安装与测试,后续挂载 NFS 共享目录:
bash
## Web1节点配置
[root@web1 ~ 11:37:44]# yum install -y nginx # 安装Nginx
[root@web1 ~ 11:38:03]# echo Welcome to $(hostname) > /usr/share/nginx/html/index.html # 写入节点标识
[root@web1 ~ 11:38:59]# systemctl enable nginx.service --now # 开机自启并启动服务
Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service.
## Web2节点配置
[root@web2 ~ 11:27:56]# yum install -y nginx
[root@web2 ~ 11:38:16]# echo Welcome to $(hostname) > /usr/share/nginx/html/index.html
[root@web2 ~ 11:38:54]# systemctl enable nginx.service --now
Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service.
## Web3节点配置
[root@web3 ~ 11:26:17]# yum install -y nginx
[root@web3 ~ 11:38:30]# echo Welcome to $(hostname) > /usr/share/nginx/html/index.html
[root@web3 ~ 11:38:48]# systemctl enable nginx.service --now
Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service.
## 验证Web节点基础访问(内部客户端测试)
[root@client1 ~ 11:31:04]# curl 10.1.8.11
Welcome to web1.liu.cloud
[root@client1 ~ 11:39:20]# curl 10.1.8.12
Welcome to web2.liu.cloud
[root@client1 ~ 11:39:22]# curl 10.1.8.13
Welcome to web3.liu.cloud
2.7 LVS-RS(Web 节点)配置
所有 Web 节点需配置虚拟网卡与 ARP 参数,适配 LVS DR 模式的网络转发规则:
bash
## 步骤1:添加dummy虚拟网卡并配置VIP(10.1.8.100/32)
# Web1节点
[root@web1 ~ 11:39:00]# nmcli connection add type dummy ifname dummy con-name dummy ipv4.method manual ipv4.addresses 10.1.8.100/32
连接 "dummy" (1ca3da5d-9d7f-420a-9c12-a15265658a33) 已成功添加。
[root@web1 ~ 11:44:55]# nmcli connection up dummy
连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/12)。
# Web2节点
[root@web2 ~ 11:38:55]# nmcli connection add type dummy ifname dummy con-name dummy ipv4.method manual ipv4.addresses 10.1.8.100/32
连接 "dummy" (159f18d9-dc94-419f-8aa1-2c5ab1426ffd) 已成功添加。
[root@web2 ~ 11:45:06]# nmcli connection up dummy
连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/10)。
# Web3节点
[root@web3 ~ 11:38:49]# nmcli connection add type dummy ifname dummy con-name dummy ipv4.method manual ipv4.addresses 10.1.8.100/32
连接 "dummy" (66182c41-8a9a-4f9a-88a5-247b881a0d54) 已成功添加。
[root@web3 ~ 11:45:14]# nmcli connection up dummy
连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/10)。
## 步骤2:配置ARP参数(关闭dummy网卡ARP解析,避免VIP冲突)
# Web1节点
[root@web1 ~ 11:44:57]# cat >> /etc/sysctl.conf << EOF
> net.ipv4.conf.all.arp_ignore = 1
> net.ipv4.conf.all.arp_announce = 2
> net.ipv4.conf.dummy.arp_ignore = 1
> net.ipv4.conf.dummy.arp_announce = 2
> EOF
[root@web1 ~ 11:45:43]# sysctl -p # 加载ARP配置
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.dummy.arp_ignore = 1
net.ipv4.conf.dummy.arp_announce = 2
# Web2节点
[root@web2 ~ 11:45:08]# cat >> /etc/sysctl.conf << EOF
> net.ipv4.conf.all.arp_ignore = 1
> net.ipv4.conf.all.arp_announce = 2
> net.ipv4.conf.dummy.arp_ignore = 1
> net.ipv4.conf.dummy.arp_announce = 2
> EOF
[root@web2 ~ 11:45:36]# sysctl -p
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.dummy.arp_ignore = 1
net.ipv4.conf.dummy.arp_announce = 2
# Web3节点
[root@web3 ~ 11:45:15]# cat >> /etc/sysctl.conf << EOF
> net.ipv4.conf.all.arp_ignore = 1
> net.ipv4.conf.all.arp_announce = 2
> net.ipv4.conf.dummy.arp_ignore = 1
> net.ipv4.conf.dummy.arp_announce = 2
> EOF
[root@web3 ~ 11:45:31]# sysctl -p
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.dummy.arp_ignore = 1
net.ipv4.conf.dummy.arp_announce = 2
2.8 Web 节点 NFS 挂载配置
将 Web 节点的 Nginx 站点目录挂载至 NFS 共享目录,实现资源统一管理:
bash
## Web1节点NFS挂载(时间戳:12:24:45 - 12:25:42)
[root@web1 ~ 12:24:45]# yum install -y nfs-utils # 安装NFS客户端
[root@web1 ~ 12:24:52]# echo '10.1.2.100:/usr/share/nginx/html /usr/share/nginx/html nfs defaults 0 0' >> /etc/fstab # 写入挂载规则
[root@web1 ~ 12:25:15]# systemctl daemon-reload # 重新加载系统配置
[root@web1 ~ 12:25:32]# mount -a # 执行挂载
[root@web1 ~ 12:25:42]# df /usr/share/nginx/html # 验证挂载结果
文件系统 1K-块 已用 可用 已用% 挂载点
10.1.2.100:/usr/share/nginx/html 52403200 1641472 50761728 4% /usr/share/nginx/html
## Web2节点NFS挂载(时间戳:11:45:55 - 12:25:47)
[root@web2 ~ 11:45:55]# yum install -y nfs-utils
[root@web2 ~ 12:24:56]# echo '10.1.2.100:/usr/share/nginx/html /usr/share/nginx/html nfs defaults 0 0' >> /etc/fstab
[root@web2 ~ 12:25:20]# systemctl daemon-reload
[root@web2 ~ 12:25:27]# mount -a
[root@web2 ~ 12:25:47]# df /usr/share/nginx/html
文件系统 1K-块 已用 可用 已用% 挂载点
10.1.2.100:/usr/share/nginx/html 52403200 1641472 50761728 4% /usr/share/nginx/html
## Web3节点NFS挂载(时间戳:11:45:59 - 12:25:54)
[root@web3 ~ 11:45:59]# yum install -y nfs-utils
[root@web3 ~ 12:25:01]# echo '10.1.2.100:/usr/share/nginx/html /usr/share/nginx/html nfs defaults 0 0' >> /etc/fstab
[root@web3 ~ 12:25:11]# systemctl daemon-reload
[root@web3 ~ 12:25:36]# mount -a
[root@web3 ~ 12:25:54]# df /usr/share/nginx/html
文件系统 1K-块 已用 可用 已用% 挂载点
10.1.2.100:/usr/share/nginx/html 52403200 1641472 50761728 4% /usr/share/nginx/html
2.9 HA 和 LVS-DS 配置(ha1/ha2)
2.9.1 ha1 节点(主节点)配置
bash
## 步骤1:安装依赖包(时间戳:11:28:03)
[root@ha1 ~ 11:28:03]# yum install -y keepalived ipvsadm
## 步骤2:备份并编辑Keepalived配置文件(时间戳:11:46:54 - 11:47:11)
[root@ha1 ~ 11:46:54]# cp /etc/keepalived/keepalived.conf {,.bak} # 备份原有配置
[root@ha1 ~ 11:47:11]# vim /etc/keepalived/keepalived.conf # 编辑配置文件
bash
! Configuration File for keepalived
global_defs {
router_id ha1
}
vrrp_instance web {
state MASTER
interface ens33
virtual_router_id 51
priority 110
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
10.1.8.100/24
}
}
virtual_server 10.1.8.100 80 {
delay_loop 6
lb_algo rr
lb_kind DR
protocol TCP
real_server 10.1.8.11 80 {
weight 1
TCP_CHECK {
connect_timeout 3
retry 3
delay_before_retry 3
}
}
real_server 10.1.8.12 80 {
weight 2
TCP_CHECK {
connect_timeout 3
retry 3
delay_before_retry 3
}
}
real_server 10.1.8.13 80 {
weight 2
TCP_CHECK {
connect_timeout 3
retry 3
delay_before_retry 3
}
}
}
bash
## 步骤3:启动Keepalived服务(时间戳:12:15:35)
[root@ha1 ~ 12:15:35]# systemctl enable keepalived.service --now
Created symlink from /etc/systemd/system/multi-user.target.wants/keepalived.service to /usr/lib/systemd/system/k
2.9.2 ha2 节点(备节点)配置
bash
## 步骤1:安装依赖包(时间戳:10:30:56)
[root@ha2 ~ 10:30:56]# yum install -y keepalived ipvsadm
## 步骤2:备份并编辑Keepalived配置文件(时间戳:12:16:27 - 12:16:57)
[root@ha2 ~ 12:16:27]# cp /etc/keepalived/keepalived.conf {,.bak}
[root@ha2 ~ 12:16:57]# vim /etc/keepalived/keepalived.conf
bash
! Configuration File for keepalived
global_defs {
router_id ha2
}
vrrp_instance web {
state BACKUP
interface ens33
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
10.1.8.100/24
}
}
virtual_server 10.1.8.100 80 {
delay_loop 6
lb_algo rr
lb_kind DR
protocol TCP
real_server 10.1.8.11 80 {
weight 1
TCP_CHECK {
connect_timeout 3
retry 3
delay_before_retry 3
}
}
real_server 10.1.8.12 80 {
weight 1
TCP_CHECK {
connect_timeout 3
retry 3
delay_before_retry 3
}
}
real_server 10.1.8.13 80 {
weight 1
TCP_CHECK {
connect_timeout 3
retry 3
delay_before_retry 3
}
}
}
bash
## 步骤3:启动Keepalived服务(时间戳:12:23:03)
[root@ha2 ~ 12:23:03]# systemctl enable keepalived.service --now
Created symlink from /etc/systemd/system/multi-user.target.wants/keepalived.service to /usr/lib/systemd/system/keepalived.service.
2.10 集群测试
2.10.1 功能性测试
验证集群基础访问能力,通过客户端持续访问 VIP,确认服务正常:
bash
# 内部客户端测试
[root@client1 ~ 12:31:21]# while true ;do curl -s http://10.1.8.100;sleep 1;done
Welcome to www.liu.cloud
Welcome to www.liu.cloud
......
# 外部客户端测试
[root@client2 ~ 10:31:34]# while true ;do curl -s http://10.1.8.100;sleep 1;done
Welcome to www.liu.cloud
Welcome to www.liu.cloud
Welcome to www.liu.cloud
Welcome to www.liu.cloud
......
2.10.2 高可用测试
持续监控集群可用性,验证主备节点切换无感知:
bash
[root@client2 ~ 12:42:08]# while true ;do curl -s http://10.1.8.100;sleep 1;done
Welcome to www.liu.cloud
......
测试1:停止 ha1 上 keepalived 服务。
bash
[root@ha1 ~ 12:30:30]# systemctl stop keepalived.service
结果:客户端无感知故障,正常访问集群。
测试2:恢复 ha1 上 keepalived 服务。
bash
[root@ha1 ~ 12:33:10]# systemctl start keepalived.service
结果:客户端无感知故障,正常访问集群。
2.10.3 负载均衡测试
验证 LVS 健康检查与节点上下线自动识别能力:
测试1:停止 web2 上 nginx 服务,监控客户端访问情况。
bash
[root@web2 ~ 12:26:22]# systemctl stop nginx
结果:输出结果中间会出现空白,大概 15 秒,LVS 将 web2 从后端虚拟主机中剔除。
测试2:启动 web2 上 nginx 服务,监控客户端访问情况。
bash
[root@web2 ~ 12:34:25]# systemctl start nginx
结果:大概 5 秒,LVS将web2加入后端虚拟主机中。