背景介绍:为什么需要负载均衡?
在高并发 Web 服务场景中,单台后端服务器的处理能力和可用性存在明显瓶颈:
- 流量过载:单台服务器无法承载大量用户请求,易出现响应缓慢或宕机;
- 单点故障:若唯一的后端服务器崩溃,整个服务将不可用;
- 资源浪费:多台服务器闲置时无法有效分担负载,资源利用率低。
Nginx 七层负载均衡(基于 HTTP/HTTPS 协议的应用层负载均衡)是解决上述问题的核心方案:
- 将用户请求分发到多台后端服务器,提升整体处理能力;
- 实现服务冗余,某台后端服务器故障时自动切换,保障服务可用性;
- 支持多种分发算法(轮询、权重轮询、IP 哈希等),适配不同业务场景;
- 结合 Keepalived 可进一步解决负载均衡器自身的单点故障,实现端到端高可用。
本文以 CentOS 7 系统为例,从环境规划、基础配置到高可用扩展,完整讲解 Nginx 七层负载均衡架构的搭建流程,所有操作均经过验证,可直接用于测试或生产环境。
核心关键词解释
- 七层负载均衡:工作在 OSI 七层模型的应用层(HTTP/HTTPS 协议),基于请求内容(如域名、URL)分发流量,Nginx 是典型的七层负载均衡器;
- upstream 模块:Nginx 实现负载均衡的核心模块,用于定义后端服务器组及分发规则;
- 轮询算法:默认的负载均衡算法,请求按顺序轮流分发到后端服务器,适用于服务器性能一致的场景;
- 权重轮询:按服务器权重比例分发流量,权重越高的服务器接收的请求越多,适配服务器性能差异的场景;
- IP 哈希算法:根据客户端 IP 计算哈希值,将同一客户端的请求固定分发到某台后端服务器,解决会话保持问题;
- VIP(虚拟 IP):Keepalived 提供的虚拟 IP 地址,作为对外统一访问入口,故障时自动漂移到备用负载均衡器;
- Keepalived:基于 VRRP 协议的高可用工具,实现负载均衡器的双机热备,避免单点故障;
- X-Forwarded-For:HTTP 请求头字段,用于传递客户端真实 IP 地址,解决负载均衡器转发后后端日志无法识别真实客户端的问题。
一、环境规划
本次搭建涉及 3 台 CentOS 7 服务器,角色分工明确,确保架构简洁且可扩展:
| 角色 | IP 地址 | 新主机名 | 核心功能 |
|---|---|---|---|
| 后端 Web 服务器 1 | 10.1.1.11 | web1 | 部署 Web 应用(本文以 Nginx 静态页面为例) |
| 后端 Web 服务器 2 | 10.1.1.13 | web2 | 与 web1 构成后端服务集群,提供冗余能力 |
| Nginx 负载均衡器 | 10.1.1.16 | nginxLB | 运行 Nginx,实现七层(HTTP/HTTPS)流量分发 |
二、基础环境配置(三台机器均需执行)
基础环境配置是保障后续服务稳定运行的前提,主要包括主机名设置、hosts 解析、防火墙 / SELinux 关闭、网络管理工具优化及 YUM 源配置,所有操作需在三台机器上分别执行。
2.1 设置主机名
通过 hostnamectl 命令设置永久主机名,避免后续因主机名混乱导致的配置问题:
bash
# 在10.1.1.11(web1)上执行
hostnamectl set-hostname web1
# 在10.1.1.13(web2)上执行
hostnamectl set-hostname web2
# 在10.1.1.16(nginxLB)上执行
hostnamectl set-hostname nginxLB
设置完成后,可通过 hostname 命令验证,或重新登录终端生效。
2.2 配置 /etc/hosts 文件
手动配置 hosts 解析,实现三台机器间的主机名互访(无需依赖 DNS),同时避免本地解析冲突:
bash
cat > /etc/hosts <<EOF
127.0.0.1 localhost localhost.localdomain
::1 localhost localhost.localdomain
10.1.1.11 web1
10.1.1.13 web2
10.1.1.16 nginxLB
EOF
配置后可通过 ping web1、ping nginxLB 等命令测试连通性(返回响应说明解析正常)。
2.3 关闭防火墙与 SELinux
CentOS 7 默认启用的防火墙(firewalld)和 SELinux 可能会拦截 Nginx 流量(如 80 端口、VRRP 心跳包),为简化测试和部署,直接关闭并禁用:
bash
# 关闭并禁用firewalld(避免拦截HTTP请求和负载均衡器心跳包)
systemctl stop firewalld
systemctl disable firewalld
# 临时关闭SELinux(立即生效,避免权限限制导致Nginx启动失败)
setenforce 0
# 永久关闭SELinux(重启后生效,彻底禁用)
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
可通过 getenforce 命令验证 SELinux 状态(输出 Disabled 或 Permissive 即为成功)。
2.4 关闭 NetworkManager
NetworkManager 可能与传统网络配置工具(如 network 服务)冲突,尤其在服务器场景中,建议关闭并禁用:
bash
systemctl stop NetworkManager
systemctl disable NetworkManager
2.5 配置 YUM 源(阿里云镜像)
默认 YUM 源(国外)下载速度较慢,替换为阿里云镜像源,提升软件安装效率:
bash
# 安装EPEL源(提供Nginx等额外软件包)
rpm -ivh https://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm
# 创建自定义YUM源配置文件(覆盖默认源)
cat > /etc/yum.repos.d/server.repo <<EOF
[aliyun]
name=Aliyun CentOS
baseurl=http://mirrors.aliyun.com/centos/7/os/x86_64/
enabled=1
gpgcheck=0 # 关闭GPG校验,加速安装
[epel]
name=EPEL
baseurl=https://mirrors.aliyun.com/epel/7/x86_64/
enabled=1
gpgcheck=0
EOF
# 清理并生成YUM缓存(使新源生效)
yum clean all
yum makecache fast
三、在后端服务器(web1、web2)部署 Web 服务
后端服务器需提供可访问的 Web 服务,本文以 Nginx 静态页面为例(实际场景可替换为 Apache、Tomcat、Node.js 等应用服务),两台后端服务器操作类似,仅页面内容有差异(便于区分流量分发效果)。
3.1 在 web1(10.1.1.11)部署 Web 服务
bash
# 安装Nginx(从阿里云EPEL源获取)
yum install -y nginx
# 创建自定义静态页面(标识web1节点,便于测试时区分)
echo "<h1>Welcome to web1 (10.1.1.11)</h1>" > /usr/share/nginx/html/index.html
# 启动Nginx并设置开机自启(确保服务器重启后服务自动运行)
systemctl start nginx
systemctl enable nginx
3.2 在 web2(10.1.1.13)部署 Web 服务
bash
# 安装Nginx
yum install -y nginx
# 创建自定义静态页面(标识web2节点,与web1区分)
echo "<h1>Welcome to web2 (10.1.1.13)</h1>" > /usr/share/nginx/html/index.html
# 启动Nginx并设置开机自启
systemctl start nginx
systemctl enable nginx
3.3 验证后端服务
在本地或任意可访问服务器的设备上,通过浏览器或 curl 命令验证后端服务是否正常:
bash
# 访问web1(应返回web1标识页面)
curl http://10.1.1.11 # 预期输出:"<h1>Welcome to web1 (10.1.1.11)</h1>"
# 访问web2(应返回web2标识页面)
curl http://10.1.1.13 # 预期输出:"<h1>Welcome to web2 (10.1.1.13)</h1>"
若能正常返回对应页面,说明后端 Web 服务部署成功。
四、在 nginxLB(10.1.1.16)配置 Nginx 负载均衡
负载均衡器是架构的核心入口,需安装 Nginx 并配置七层负载均衡规则,实现流量向 web1、web2 分发。
4.1 安装 Nginx(使用官方源)
为确保 Nginx 版本较新且稳定(支持更多负载均衡特性),采用 Nginx 官方 YUM 源安装:
bash
# 安装依赖包(编译Nginx需用到pcre、zlib等库)
yum install -y yum-utils pcre-devel zlib-devel openssl-devel
# 添加Nginx官方仓库配置(CentOS 7专用)
cat > /etc/yum.repos.d/nginx.repo <<EOF
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/7/\$basearch/
gpgcheck=1 # 开启GPG校验,确保包完整性
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key # 官方签名密钥
module_hotfixes=true
EOF
# 安装Nginx(从官方源获取最新稳定版)
yum install -y nginx
# 启动Nginx并设置开机自启
systemctl start nginx
systemctl enable nginx
4.2 配置七层负载均衡规则
编辑 Nginx 主配置文件 /etc/nginx/nginx.conf,核心是定义 upstream 后端服务器组,并在 server 块中通过 proxy_pass 转发流量。
基础配置(轮询算法)
默认轮询算法适合后端服务器性能一致的场景,流量会均匀分发到 web1 和 web2:
nginx
http {
# ... 保留文件中其他默认配置(如log_format、sendfile、keepalive_timeout等) ...
# 1. 定义后端服务器组(命名为shop,可自定义,需与proxy_pass对应)
upstream shop {
server 10.1.1.11; # web1节点(默认权重1)
server 10.1.1.13; # web2节点(默认权重1)
# 可选参数:
# - down:标记节点不可用(临时下线)
# - backup:备用节点(仅主节点全部故障时生效)
# - weight=2:设置权重(如server 10.1.1.11 weight=2;)
}
# 2. 配置负载均衡入口(监听80端口,域名www.shop.com)
server {
listen 80;
server_name www.shop.com; # 实际场景建议用域名,测试可直接用负载均衡器IP(10.1.1.16)
# 3. 所有请求转发到upstream服务器组
location / {
proxy_pass http://shop; # 与upstream名称一致(shop)
# 4. 传递客户端真实IP和请求头(关键!否则后端日志仅记录负载均衡器IP)
proxy_set_header Host $host; # 传递客户端请求的Host头
proxy_set_header X-Real-IP $remote_addr; # 传递客户端真实IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 传递经过的代理IP链
}
}
# ... 保留文件中其他默认配置(如默认server块可注释或删除,避免冲突) ...
}
可选:其他负载均衡算法
根据实际场景需求,可替换 upstream 中的算法,常见方案如下:
1. 权重轮询(适配服务器性能差异)
nginx
upstream shop {
server 10.1.1.11 weight=8; # web1权重8,承担80%流量(性能更强)
server 10.1.1.13 weight=2; # web2权重2,承担20%流量(性能较弱)
}
2. IP 哈希(解决会话保持)
nginx
upstream shop {
ip_hash; # 启用IP哈希算法(同一客户端IP固定分发到某台后端服务器)
server 10.1.1.11;
server 10.1.1.13;
}
4.3 验证负载均衡配置
配置完成后,需检查配置语法并重启 Nginx 使配置生效:
bash
# 检查Nginx配置语法(关键!避免配置错误导致服务启动失败)
nginx -t
# 若语法正确(输出"nginx: configuration file /etc/nginx/nginx.conf test is successful"),重启Nginx
systemctl restart nginx
五、优化 Web 服务器日志(获取真实客户端 IP)
默认情况下,后端 Web 服务器(web1、web2)的访问日志仅记录负载均衡器(10.1.1.16)的 IP,无法定位真实客户端。需通过修改后端 Nginx 日志格式,提取 X-Forwarded-For 字段中的真实 IP。
5.1 在 web1 和 web2 上修改日志配置
分别在 web1 和 web2 上编辑 /etc/nginx/nginx.conf,修改 http 块中的日志格式:
nginx
http {
# ... 其他默认配置(如include /etc/nginx/conf.d/*.conf;等) ...
# 定义包含真实IP的日志格式(替换默认main格式)
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"'; # 新增$http_x_forwarded_for字段(真实客户端IP)
# 启用自定义日志格式(应用到access_log)
access_log /var/log/nginx/access.log main;
# ... 其他默认配置(如error_log、sendfile等) ...
}
5.2 重启后端 Nginx 并验证
bash
# 在web1和web2上分别执行(使日志配置生效)
systemctl restart nginx
# 测试后查看访问日志(验证真实IP是否记录)
tail -f /var/log/nginx/access.log
当通过负载均衡器访问服务后,日志中 "$http_x_forwarded_for" 字段会显示客户端真实 IP(如 192.168.1.100),而非负载均衡器 IP(10.1.1.16)。
六、测试负载均衡效果
负载均衡配置完成后,需通过客户端测试流量是否正常分发,主要有两种测试方式。
6.1 本地 hosts 绑定(模拟域名访问)
若配置中使用 www.shop.com 域名(而非直接用负载均衡器 IP),需在客户端(如 Windows、Mac)配置 hosts 解析,将域名指向负载均衡器 IP:
-
Windows 客户端 :编辑
C:\Windows\System32\drivers\etc\hosts,添加:plaintext
10.1.1.16 www.shop.com -
Linux/Mac 客户端 :编辑
/etc/hosts,添加同上内容。
配置后,打开浏览器访问 http://www.shop.com,反复刷新页面,应交替显示 web1 和 web2 的页面(轮询算法),说明流量已正常分发。
6.2 直接 curl 测试(无图形界面场景)
在任意可访问负载均衡器的设备上,通过 curl 命令多次执行,观察返回结果:
bash
# 多次执行curl命令(访问负载均衡器IP)
curl http://10.1.1.16 # 或curl http://www.shop.com(已配置hosts时)
若返回结果交替出现 web1 和 web2 的页面内容(如 Welcome to web1 和 Welcome to web2),证明负载均衡生效。
七、可选:实现高可用(Keepalived + 双 Nginx)
上述架构中,负载均衡器(nginxLB)是单点故障风险点 ------ 若 nginxLB 宕机,所有后端服务将无法对外提供访问。通过 Keepalived 双机热备 可解决此问题,核心是添加一台备用负载均衡器,通过虚拟 IP(VIP)实现故障自动切换。
7.1 环境扩展
新增一台 CentOS 7 服务器作为备用负载均衡器:
| 角色 | IP 地址 | 主机名 | 核心功能 |
|---|---|---|---|
| 备用 Nginx 负载均衡器 | 10.1.1.17 | nginxLB2 | 与 nginxLB 配置一致,备用节点 |
| 虚拟 IP(VIP) | 10.1.1.100 | - | 对外统一入口,故障时自动漂移 |
7.2 配置备用负载均衡器(nginxLB2)
- 基础环境配置:执行本文 "第二步 基础环境配置" 的所有操作(主机名、hosts、防火墙、SELinux、YUM 源等);
- 安装并配置 Nginx :完全复制 nginxLB(10.1.1.16)的 Nginx 配置(包括
upstream后端服务器组、server转发规则等),确保两台负载均衡器配置一致; - 验证 Nginx :启动 Nginx,执行
curl http://10.1.1.17测试,应能正常分发流量到 web1 和 web2。
7.3 在两台负载均衡器上安装 Keepalived
bash
# 在nginxLB(10.1.1.16)和nginxLB2(10.1.1.17)上分别执行
yum install -y keepalived # 从YUM源安装Keepalived
7.4 配置 Keepalived(主备差异化)
Keepalived 核心配置文件为 /etc/keepalived/keepalived.conf,主备节点配置略有差异(主节点优先级更高)。
主负载均衡器(nginxLB,10.1.1.16)配置
conf
global_defs {
router_id nginxLB # 节点唯一标识,主备需不同(主节点为nginxLB,备节点为nginxLB2)
}
# 健康检查:监控Nginx是否存活,若Nginx宕机则停止Keepalived(触发VIP漂移)
vrrp_script check_nginx {
script "/etc/keepalived/check_nginx.sh" # 健康检查脚本路径(需手动创建)
interval 2 # 检查间隔(2秒,平衡性能和灵敏度)
weight 2 # 权重调整(脚本执行成功则节点优先级+2,失败则-2)
}
vrrp_instance VI_1 {
state MASTER # 主节点标识(备节点为BACKUP)
interface ens33 # 网卡名(通过ip a查看实际网卡,如eth0、ens192)
virtual_router_id 51 # 虚拟路由ID(0-255,主备必须一致,标识同一VRRP组)
priority 100 # 优先级(主节点高于备节点,如100>90)
advert_int 1 # 心跳间隔(1秒,主备节点通过组播交换心跳包)
# 认证配置(主备必须一致,防止非法节点加入VRRP组)
authentication {
auth_type PASS # 认证类型(PASS为密码认证)
auth_pass 1111 # 认证密码(4-8位数字,主备相同)
}
# 虚拟IP(VIP)配置(对外统一访问入口)
virtual_ipaddress {
10.1.1.100/24 # VIP地址及子网掩码(与服务器同网段)
}
# 关联健康检查脚本(监控Nginx状态)
track_script {
check_nginx
}
}
备负载均衡器(nginxLB2,10.1.1.17)配置
conf
global_defs {
router_id nginxLB2 # 备节点唯一标识,与主节点(nginxLB)区分
}
# 健康检查脚本配置(与主节点完全一致)
vrrp_script check_nginx {
script "/etc/keepalived/check_nginx.sh" # 同主节点的健康检查脚本路径
interval 2 # 每2秒检查一次Nginx状态
weight 2 # 脚本执行结果影响节点优先级(成功+2,失败-2)
}
vrrp_instance VI_1 {
state BACKUP # 角色为备节点
interface ens33 # 需与主节点一致(通过ip a命令确认实际网卡名,如eth0、ens192)
virtual_router_id 51 # 必须与主节点相同(0-255之间,标识同一VRRP组)
priority 90 # 优先级低于主节点(主100,备90),确保主节点优先抢占VIP
advert_int 1 # 主备节点心跳间隔1秒
# 认证配置(主备必须完全一致,防止非法节点接入)
authentication {
auth_type PASS
auth_pass 1111 # 4-8位数字密码,主备保持统一
}
# 虚拟IP(VIP)配置,与主节点完全一致
virtual_ipaddress {
10.1.1.100/24 # 对外提供服务的统一VIP,子网掩码与服务器一致
}
# 关联健康检查脚本,监控Nginx存活状态
track_script {
check_nginx
}
}
7.5 创建 Nginx 健康检查脚本(两台 LB 均需执行)
健康检查脚本的核心作用:当 Nginx 服务崩溃时,自动停止当前节点的 Keepalived,避免 "Nginx 死了但 VIP 还在" 的假活状态,确保 VIP 漂移到正常节点。
步骤 1:创建脚本文件
bash
# 在两台负载均衡器(nginxLB、nginxLB2)上分别执行
cat > /etc/keepalived/check_nginx.sh <<'EOF'
#!/bin/bash
# 检查Nginx进程是否存在(通过进程名nginx判断)
nginx_pid=$(ps -C nginx --no-header | wc -l)
# 若Nginx进程数为0(说明Nginx已停止),则停止Keepalived
if [ $nginx_pid -eq 0 ]; then
echo "Nginx is down, stopping Keepalived..." >> /var/log/keepalived_check.log
systemctl stop keepalived
fi
EOF
步骤 2:赋予脚本执行权限
bash
# 两台LB均执行,确保脚本可运行(否则健康检查失效)
chmod +x /etc/keepalived/check_nginx.sh
7.6 启动 Keepalived 并设置开机自启(两台 LB 均需执行)
bash
# 启动Keepalived服务
systemctl start keepalived
# 设置开机自启(避免服务器重启后服务未启动)
systemctl enable keepalived
# 查看Keepalived状态,确认启动成功(输出active (running))
systemctl status keepalived
7.7 高可用效果验证
验证 1:VIP 绑定状态
-
主节点(nginxLB,10.1.1.16) :执行
ip a show ens33(替换为实际网卡名),应看到 VIP10.1.1.100/24已绑定,示例如下:plaintext
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:xx:xx:xx brd ff:ff:ff:ff:ff:ff inet 10.1.1.16/24 brd 10.1.1.255 scope global noprefixroute ens33 valid_lft forever preferred_lft forever inet 10.1.1.100/24 scope global secondary ens33 # VIP已绑定(关键) valid_lft forever preferred_lft forever -
备节点(nginxLB2,10.1.1.17):执行相同命令,无 VIP 绑定(正常待命状态)。
验证 2:模拟主节点故障(Nginx 宕机)
在主节点(nginxLB,10.1.1.16)上手动停止 Nginx,观察 VIP 漂移:
bash
# 停止主节点的Nginx服务(模拟故障)
systemctl stop nginx
# 查看健康检查日志(可选,确认脚本执行)
tail -f /var/log/keepalived_check.log # 应显示"Nginx is down, stopping Keepalived..."
# 查看主节点VIP状态(应消失)
ip a show ens33
# 查看备节点VIP状态(应自动绑定)
ssh 10.1.1.17 "ip a show ens33"
预期结果:
- 主节点 Keepalived 被健康检查脚本停止,VIP 消失;
- 备节点检测到主节点心跳中断,自动绑定 VIP
10.1.1.100; - 客户端访问
http://10.1.1.100(或绑定的域名),服务正常,无感知切换。
验证 3:恢复主节点服务
修复主节点 Nginx 后,重启服务,观察 VIP 抢占(默认抢占模式):
bash
# 在主节点(nginxLB)执行
# 1. 重启Nginx(恢复服务)
systemctl start nginx
# 2. 重启Keepalived(重新加入VRRP组)
systemctl start keepalived
# 3. 查看VIP状态(应重新绑定到主节点)
ip a show ens33
预期结果:主节点重启后,因优先级(100)高于备节点(90),自动抢占 VIP,备节点 VIP 消失,恢复主备正常状态。
7.8 高可用配置注意事项
-
网卡名一致性 :主备节点的
interface必须是实际网卡名(通过ip a确认),若不一致会导致 VIP 绑定失败; -
关闭 vrrp_strict :若 Keepalived 版本 ≥1.3.0,需在
keepalived.conf中注释vrrp_strict(否则 VIP 无法 ping 通,影响客户端访问); -
配置一致性 :两台 LB 的 Nginx 配置(
upstream、转发规则等)必须完全一致,避免切换后服务异常; -
防脑裂措施 :若生产环境需开启防火墙,需放行 VRRP 协议(端口 112),确保主备心跳正常:
bash
# 两台LB均执行(若开启firewalld) firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 0 --protocol vrrp -j ACCEPT firewall-cmd --reload -
非抢占模式(可选) :默认抢占模式可能导致不必要的切换(主节点恢复后立即抢占 VIP),生产环境可启用非抢占模式(主备节点
state均设为BACKUP,添加nopreempt参数)。
八、总结
本文基于 CentOS 7 搭建了完整的 Nginx 七层负载均衡架构,核心亮点包括:
- 基础架构:通过 Nginx 实现 HTTP 层流量分发,支持轮询、权重轮询、IP 哈希等算法,适配不同业务场景;
- 真实 IP 传递 :通过
proxy_set_header配置和日志优化,确保后端服务器能获取客户端真实 IP,便于问题排查; - 高可用扩展:通过 Keepalived 双机热备解决负载均衡器单点故障,VIP 自动漂移实现业务无感知切换。
该架构适用于中小型 Web 服务集群,具备部署简单、稳定性高、可扩展性强的特点。实际生产环境中,可根据业务需求进一步优化(如添加 SSL 证书实现 HTTPS 负载均衡、配置 Nginx 缓存提升性能、后端服务健康检查自动下线故障节点等),提升服务性能和安全性。