技术博客:Nginx高可用负载均衡在武汉多机房架构中的实践

2026-08-07 技术博客 阅读

业务背景

我们服务的某武汉电商平台,日均PV 200万+,峰值 QPS 3000+。最初部署在光谷单一机房,但随着业务增长,面临以下问题:

  • 单点故障风险:机房断电/断网导致全网不可用
  • 跨区域访问慢:沌口/汉口用户访问光谷机房延迟较高
  • 容量瓶颈:大促期间单机房资源不足

决定采用双机房架构:光谷主机房 + 沌口备用机房。

架构设计

                    ┌──────────────┐
│ DNS 智能解析 │
│ (阿里云DNS) │
└──────┬───────┘

┌────────────┼────────────┐
▼ ▼ ▼
┌────────────┐ ┌────────────┐ ┌────────────┐
│ 光谷-LB-M │ │ 光谷-LB-S │ │ 沌口-LB │
│ (Master) │ │ (Slave) │ │ (Backup) │
│ Nginx+Keepalived │ Nginx+Keepalived │
└─────┬──────┘ └─────┬──────┘ └─────┬──────┘
│ │ │
└──────┬───────┘ │
▼ ▼
┌────────────┐ ┌────────────┐
│ 光谷业务集群│ │ 沌口业务集群│
│ (Web×6) │ │ (Web×3) │
│ (DB主+从) │ │ (DB只读) │
│ (Redis集群) │ │ (Redis从) │
└────────────┘ └────────────┘

Nginx 负载均衡配置

基础配置

# nginx.conf
worker_processes auto;
worker_rlimit_nofile 65535;

events {
worker_connections 10240;
use epoll;
multi_accept on;
}

http {
include mime.types;
default_type application/octet-stream;

# 日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'upstream_addr=$upstream_addr '
'upstream_response_time=$upstream_response_time';

sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;

# Gzip 压缩
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css application/json application/javascript text/xml;

# 上游服务器组
upstream guanggu_backend {
server 10.0.1.101:8080 weight=5 max_fails=3 fail_timeout=30s;
server 10.0.1.102:8080 weight=5 max_fails=3 fail_timeout=30s;
server 10.0.1.103:8080 weight=5 max_fails=3 fail_timeout=30s;
server 10.0.1.104:8080 weight=5 max_fails=3 fail_timeout=30s;
server 10.0.1.105:8080 weight=5 max_fails=3 fail_timeout=30s;
server 10.0.1.106:8080 weight=5 max_fails=3 fail_timeout=30s;
keepalive 32; # 长连接池
}

upstream zhuankou_backend {
server 10.0.2.201:8080 weight=3 max_fails=3 fail_timeout=30s;
server 10.0.2.202:8080 weight=3 max_fails=3 fail_timeout=30s;
server 10.0.2.203:8080 weight=3 max_fails=3 fail_timeout=30s;
keepalive 16;
}

server {
listen 80;
server_name www.example.com;

location / {
proxy_pass http://guanggu_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 5s;
proxy_read_timeout 30s;
proxy_send_timeout 30s;
}

# 健康检查页面
location /health {
access_log off;
return 200 'OK';
add_header Content-Type text/plain;
}

# Nginx 状态页
location /nginx_status {
stub_status on;
allow 10.0.0.0/8; # 仅允许内网访问
deny all;
}
}
}

Keepalived 高可用配置

# 光谷 Master 节点 keepalived.conf
! Configuration File for keepalived

global_defs {
router_id LB_GUANGGU_MASTER
notification_email {
ops@example.com
}
notification_email_from keepalived@example.com
smtp_server 127.0.0.1
smtp_connect_timeout 30
}

vrrp_instance VI_1 {
state MASTER # 主节点
interface eth0 # 绑定网卡
virtual_router_id 51 # VRRP 路由 ID(同一集群须一致)
priority 110 # 优先级(主 > 备)
advert_int 1 # 心跳间隔(秒)
authentication {
auth_type PASS
auth_pass your_secret_password
}
virtual_ipaddress {
10.0.0.100 # VIP(虚拟 IP)
}
track_script {
check_nginx # 检测 Nginx 是否存活
}
}

vrrp_script check_nginx {
script "/usr/local/bin/check_nginx.sh"
interval 2 # 每2秒检测一次
weight -5 # 检测失败时优先级减5
fall 3 # 连续3次失败判定为宕机
rise 2 # 连续2次成功判定为恢复
}
# 光谷 Slave 节点 keepalived.conf(仅列出差异部分)
vrrp_instance VI_1 {
state BACKUP
priority 100 # 低于 Master
# ... 其余相同 ...
}

健康检测脚本

# /usr/local/bin/check_nginx.sh
#!/bin/bash
count=$(ps aux | grep nginx | grep -v grep | wc -l)
if [ $count -eq 0 ]; then
exit 1 # Nginx 未运行
fi

# 检测 Nginx 是否能正常响应
code=$(curl -s -o /dev/null -w "%{http_code}" http://localhost/health)
if [ $code != "200" ]; then
exit 1 # Nginx 异常
fi

exit 0

DNS 智能解析配置

在阿里云 DNS 配置:

  • 默认解析指向 VIP:10.0.0.100(光谷主)
  • 武汉电信用户 → 光谷 VIP
  • 武汉联通用户 → 光谷 VIP
  • 沌口附近用户 → 沌口 LB 直连 IP
  • 海外用户 → 沌口 LB(备用线路)

故障切换测试

测试1:Nginx 进程崩溃

# 在 Master 节点模拟 Nginx 崩溃
$ sudo killall -9 nginx

# 观察 Keepalived 日志
$ tail -f /var/log/messages
# [INFO] Nginx health check failed!
# [WARNING] VRRP_Instance(VI_1) Transition to FAULT state
# [NOTICE] VIP released

# Slave 节点接管
# [NOTICE] Received higher priority advert
# [INFO] Becoming MASTER state
# [NOTICE] VIP acquired: 10.0.0.100

# 切换时间:约 3 秒(advert_int × fall + 抢占时间)

测试2:Master 整机宕机

# 直接关闭 Master 服务器电源

# Slave 节点日志
# [WARNING] Master not responding!
# [NOTICE] Transition to MASTER state
# [NOTIVE] VIP acquired

# 切换时间:约 3 秒(advert_int × 3 次 missed)

# 对用户的影响:约 3 秒的部分请求返回 502

测试3:Master 恢复

# 重启 Master 服务器

# Master 日志
# [NOTICE] Higher priority advert received
# [INFO] Transition to MASTER state
# [NOTICE] VIP acquired back

# 注意:默认配置下 Master 恢复后会抢占 VIP
# 如需避免频繁切换,Slave 可设置 nopreempt

监控告警

# 使用 Zabbix 监控
# 监控项:
# 1. VIP 所在节点(应该在 Master 上)
# 2. Nginx 进程状态
# 3. 后端服务器健康状态(up/down 数量)
# 4. QPS 和响应时间
# 5. Keepalived 状态切换事件

# 告警规则:
# - VIP 漂移 → P0 立即通知
# - 后端服务器 down 超过 1 台 → P1 通知
# - QPS 超过阈值 → P2 通知
# - 响应时间 P99 > 3s → P2 通知

运行数据

双机房架构上线 6 个月的数据:

  • 可用性:99.998%(仅 1 次短暂故障,因光谷机房电力检修主动切换)
  • 平均响应时间:光谷用户 45ms,沌口用户 62ms(之前统一 85ms)
  • 故障切换次数:3 次(1 次计划内,2 次意外)
  • 平均切换时间:3.2 秒
  • 双十一峰值 QPS:8500(平稳承载)

相关推荐

技术博客:基于Vue3+Vite构建高性能武汉企业官网的最佳实践

分享使用Vue3+Vite技术栈构建武汉企业官网的技术实践经验,涵盖项目架构、性能优化、SEO适配、部署方案等内容。

技术博客:武汉餐饮小程序开发实战——从0到上线全记录

详细记录为武汉某餐饮连锁开发微信小程序的全过程,包括需求分析、技术选型、功能实现、上线运营等技术细节。

技术博客:PostgreSQL在武汉政务项目中的分区表优化实践

分享在某武汉政务项目中使用PostgreSQL分区表处理海量数据的实践经验,包括分区策略、查询优化、维护自动化等。

电话咨询 微信咨询 在线咨询 返回顶部
xycx202108

微信扫码咨询

×