Nginx负载均衡架构实战:反向代理、多算法调度与高可用Web服务

一、Nginx负载均衡概述

1.1 负载均衡的价值

负载均衡是现代Web架构的核心组件,它解决以下问题:

  • 高并发处理:将请求分发到多个后端服务器
  • 高可用保障:单点故障不影响整体服务
  • 可扩展性:动态添加或移除后端服务器
  • 性能优化:充分利用多服务器资源
  • 流量控制:智能分配请求到合适的服务器

1.2 Nginx负载均衡架构

Nginx负载均衡优势

  • 反向代理与负载均衡集成
  • 多种负载均衡算法
  • 健康检查与故障自动移除
  • 会话保持支持
  • 7层负载均衡(基于HTTP)

二、基础负载均衡配置

2.1 upstream块配置

基础upstream配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# nginx.conf

http {
# 定义后端服务器组
upstream backend_servers {
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080;
}

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

location / {
proxy_pass http://backend_servers;

# 设置代理头
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}

2.2 服务器状态标记

upstream服务器参数

1
2
3
4
5
6
7
8
9
10
11
12
13
upstream backend_servers {
# 正常服务器
server 192.168.1.10:8080;

# 标记为备用服务器
server 192.168.1.11:8080 backup;

# 标记为宕机(保持配置但不接收请求)
server 192.168.1.12:8080 down;

# 临时禁用该服务器
# server 192.168.1.13:8080;
}

2.3 完整的负载均衡配置示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# nginx.conf - 完整负载均衡配置

http {
# 定义upstream块
upstream web_backend {
server 192.168.1.10:8080 weight=3 max_fails=3 fail_timeout=30s;
server 192.168.1.11:8080 weight=2 max_fails=3 fail_timeout=30s;
server 192.168.1.12:8080 weight=1 max_fails=3 fail_timeout=30s backup;

# 负载均衡算法
# 默认: 轮询
# least_conn; # 最少连接数
# ip_hash; # IP哈希
# fair; # 响应时间(需要第三方模块)
# consistent_hash $request_uri; # 一致性哈希
}

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

location / {
proxy_pass http://web_backend;

# 代理配置
proxy_http_version 1.1;
proxy_set_header Connection "";

# 请求头设置
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 10s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;

# 缓冲设置
proxy_buffering on;
proxy_buffer_size 8k;
proxy_buffers 16 8k;
proxy_busy_buffers_size 16k;

# 错误页面
proxy_intercept_errors on;
error_page 502 503 504 /50x.html;
}

location = /50x.html {
root /usr/share/nginx/html;
}
}
}

三、负载均衡算法

3.1 轮询算法(Round Robin)

轮询是Nginx的默认算法,按顺序将请求分发到后端服务器。

轮询算法配置

1
2
3
4
5
6
7
8
9
10
11
12
13
upstream backend_servers {
# 默认轮询算法
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080;
}

# 请求分发:
# 请求1 → Server1
# 请求2 → Server2
# 请求3 → Server3
# 请求4 → Server1
# ...

3.2 加权轮询算法(Weighted Round Robin)

根据服务器权重分配请求,权重越大处理的请求越多。

加权轮询配置

1
2
3
4
5
6
7
8
9
10
upstream backend_servers {
server 192.168.1.10:8080 weight=5; # 处理50%的请求
server 192.168.1.11:8080 weight=3; # 处理30%的请求
server 192.168.1.12:8080 weight=2; # 处理20%的请求
}

# 请求分发示例(每10个请求):
# Server1 (权重5): 请求1,3,6,8,10
# Server2 (权重3): 请求2,5,9
# Server3 (权重2): 请求4,7

适用场景

  • 服务器性能差异大
  • 需要为不同服务器分配不同流量
  • 逐步释放流量到新服务器

3.3 IP哈希算法(IP Hash)

基于客户端IP进行哈希计算,确保同一IP的请求总被转发到同一服务器。

IP哈希配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
upstream backend_servers {
ip_hash; # 启用IP哈希算法
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080;
}

# IP哈希工作原理:
# hash(客户端IP) % 服务器数量 = 目标服务器
#
# 示例:
# 192.168.1.100 → 始终转发到Server1
# 192.168.1.101 → 始终转发到Server2
# 192.168.1.102 → 始终转发到Server3

适用场景

  • 需要会话保持的应用
  • 有状态的Web应用
  • 避免会话丢失导致用户重新登录

注意事项

  • 服务器数量变化会导致原有哈希失效
  • 无法与backup服务器标记同时使用

3.4 一致性哈希算法(Consistent Hash)

一致性哈希在服务器增减时最小化数据迁移。

一致性哈希配置

1
2
3
4
5
6
7
8
# 需要第三方模块 nginx_upstream_hash

upstream backend_servers {
consistent_hash $request_uri;
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080;
}

一致性哈希优势

  • 服务器增减时仅影响少量请求
  • 负载分布相对均匀
  • 适合大规模集群

适用场景

  • 动态扩缩容场景
  • 缓存服务器集群
  • CDN节点分配

3.5 最少连接算法(Least Connections)

将请求转发到当前连接数最少的服务器。

最少连接配置

1
2
3
4
5
6
upstream backend_servers {
least_conn; # 最少连接数算法
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080;
}

适用场景

  • 请求处理时间差异较大的场景
  • 长连接应用(如WebSocket)
  • 需要平衡服务器负载

3.6 算法对比总结

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
负载均衡算法对比:
轮询 (Round Robin):
优点: 简单、均衡
缺点: 不考虑服务器性能
适用: 服务器性能相同

加权轮询 (Weighted Round Robin):
优点: 可按性能分配流量
缺点: 静态分配
适用: 服务器性能差异大

IP哈希 (IP Hash):
优点: 会话保持
缺点: 服务器变化影响所有客户端
适用: 有状态的Web应用

最少连接 (Least Connections):
优点: 动态负载均衡
缺点: 需要维护连接数统计
适用: 长连接、处理时间差异大

一致性哈希 (Consistent Hash):
优点: 动态扩缩容友好
缺点: 配置复杂
适用: 大规模分布式系统

四、健康检查机制

4.1 健康检查配置

健康检查自动检测后端服务器状态,及时移除故障服务器。

基础健康检查

1
2
3
4
5
upstream backend_servers {
server 192.168.1.10:8080 max_fails=3 fail_timeout=30s;
server 192.168.1.11:8080 max_fails=3 fail_timeout=30s;
server 192.168.1.12:8080 max_fails=3 fail_timeout=30s;
}

健康检查参数

  • max_fails:最大失败次数
  • fail_timeout:失败后等待时间
  • 连续失败3次则在30秒内不再转发

高级健康检查(第三方模块)

1
2
3
4
5
6
7
8
9
10
11
# 使用nginx_upstream_check_module

upstream backend_servers {
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080;

check interval=3000 rise=2 fall=3 timeout=1000 type=http;
check_http_send "GET /health HTTP/1.0\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
}

健康检查配置说明

  • interval=3000:每3秒检查一次
  • rise=2:连续2次成功才标记为UP
  • fall=3:连续3次失败才标记为DOWN
  • timeout=1000:检查超时时间1秒
  • type=http:使用HTTP健康检查
  • check_http_send:发送的HTTP请求
  • check_http_expect_alive:认为是健康的HTTP状态码

4.2 健康检查实现

后端健康检查端点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// Spring Boot健康检查Controller
@RestController
public class HealthController {

@GetMapping("/health")
public ResponseEntity<Map<String, String>> health() {
Map<String, String> status = new HashMap<>();

// 检查数据库连接
try {
dataSource.getConnection();
status.put("database", "UP");
} catch (Exception e) {
status.put("database", "DOWN");
return ResponseEntity.status(503).body(status);
}

// 检查Redis连接
try {
redisTemplate.opsForValue().get("health");
status.put("redis", "UP");
} catch (Exception e) {
status.put("redis", "DOWN");
return ResponseEntity.status(503).body(status);
}

status.put("status", "UP");
return ResponseEntity.ok(status);
}
}

Python健康检查端点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# Flask健康检查
from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/health')
def health_check():
health_status = {
'status': 'UP',
'database': check_database(),
'redis': check_redis(),
'timestamp': datetime.now().isoformat()
}

# 如果任何组件DOWN,返回503
if any(v == 'DOWN' for v in health_status.values() if isinstance(v, str)):
return jsonify(health_status), 503

return jsonify(health_status), 200

def check_database():
try:
db_connection = get_database_connection()
db_connection.execute("SELECT 1")
return "UP"
except Exception as e:
return "DOWN"

def check_redis():
try:
redis_client.ping()
return "UP"
except Exception as e:
return "DOWN"

五、会话保持配置

5.1 会话保持问题

在无状态的负载均衡环境中,会话丢失是常见问题:

会话丢失场景

  1. 用户登录后,session存储在Server1
  2. 后续请求被负载均衡到Server2
  3. Server2找不到session,用户被迫重新登录

5.2 基于IP哈希的会话保持

IP哈希配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
upstream backend_servers {
ip_hash; # 启用IP哈希
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080;
}

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

location / {
proxy_pass http://backend_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

IP哈希的局限性

  • 同一NAT后的多个用户会被哈希到同一服务器
  • 公网IP变化的移动用户会被重新分发
  • 服务器数量变化会导致原有哈希失效

5.3 基于Cookie的会话保持

Sticky模块配置

1
2
3
4
5
6
7
8
# 编译nginx时需要添加--with-http_sticky_module

upstream backend_servers {
sticky expires=1h domain=example.com path=/;
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080;
}

Sticky工作原理

  1. 第一个请求:Nginx选择服务器并设置cookie
  2. 后续请求:根据cookie将请求转发到同一服务器
  3. Cookie过期或消失时重新选择服务器

Nginx配置示例

1
2
3
4
5
6
7
8
upstream backend_servers {
# sticky模块配置
sticky name=route expires=1h domain=example.com path=/ httponly secure;

server 192.168.1.10:8080 route=a;
server 192.168.1.11:8080 route=b;
server 192.168.1.12:8080 route=c;
}

5.4 外部Session存储

将会话存储在外部缓存(如Redis),所有服务器共享会话。

Spring Boot Session配置

1
2
3
4
5
6
7
8
9
10
11
12
# application.yml
spring:
session:
store-type: redis
redis:
flush-mode: immediate
namespace: spring:session

server:
servlet:
session:
timeout: 30m
1
2
3
4
5
6
7
8
9
<!-- pom.xml -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>

六、高可用负载均衡架构

6.1 主备Nginx配置

Keepalived配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# /etc/keepalived/keepalived.conf

global_defs {
router_id nginx-main
}

vrrp_script chk_nginx {
script "/etc/keepalived/check_nginx.sh"
interval 2
weight -5
fall 3
rise 2
}

vrrp_instance VI_NGINX {
state MASTER
interface eth0
virtual_router_id 100
priority 100
advert_int 1

authentication {
auth_type PASS
auth_pass nginx-secret
}

virtual_ipaddress {
192.168.1.100
}

track_script {
chk_nginx
}

notify_master "/etc/keepalived/notify_master.sh"
notify_backup "/etc/keepalived/notify_backup.sh"
}
1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash
# check_nginx.sh - Nginx健康检查

if ! systemctl is-active --quiet nginx; then
exit 1
fi

if ! curl -f http://localhost/nginx-health > /dev/null 2>&1; then
exit 1
fi

exit 0

6.2 Nginx集群架构

多Nginx节点配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Nginx集群架构:
负载均衡层:
- Nginx-1 (主)
- Nginx-2 (主)
- Nginx-3 (主)

负载均衡策略:
- DNS轮询
- 或使用专业的负载均衡设备

后端服务器:
- Web-1, Web-2, Web-3
- Web-4, Web-5, Web-6
- Web-7, Web-8, Web-9

配置同步脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/bash
# sync_nginx_config.sh - 同步Nginx配置

NGINX_NODES=("192.168.1.100" "192.168.1.101" "192.168.1.102")
CONFIG_FILE="/etc/nginx/nginx.conf"

# 检查配置
nginx -t

if [ $? -eq 0 ]; then
# 同步到所有节点
for node in "${NGINX_NODES[@]}"; do
echo "同步配置到: $node"
scp $CONFIG_FILE "root@$node:/etc/nginx/nginx.conf"
ssh "root@$node" "nginx -t && systemctl reload nginx"
done
else
echo "配置文件错误,同步失败"
exit 1
fi

七、性能优化配置

7.1 Nginx性能优化

Worker进程优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# nginx.conf
user nginx;
worker_processes auto;
worker_cpu_affinity auto;
worker_rlimit_nofile 65535;

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

http {
# 文件描述符优化
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;

# 缓冲优化
client_body_buffer_size 128k;
client_header_buffer_size 4k;
large_client_header_buffers 4 16k;

# 负载均衡优化
upstream backend_servers {
server 192.168.1.10:8080 weight=3 max_fails=3 fail_timeout=30s;
server 192.168.1.11:8080 weight=3 max_fails=3 fail_timeout=30s;
server 192.168.1.12:8080 weight=2 max_fails=3 fail_timeout=30s;

# Keepalive连接池
keepalive 64;
keepalive_timeout 60s;
keepalive_requests 100;
}

server {
location / {
proxy_pass http://backend_servers;

# HTTP/1.1优化
proxy_http_version 1.1;
proxy_set_header Connection "";

# 其他配置...
}
}
}

7.2 限流与防爬虫

限流配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 定义限流zone
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
limit_req_zone $server_name zone=server_limit:10m rate=1000r/s;

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

# 全局限流
limit_req zone=server_limit burst=20 nodelay;

# API限流
location /api/ {
limit_req zone=api_limit burst=5 nodelay;
proxy_pass http://backend_servers;
}
}

八、实战案例

8.1 电商系统负载均衡

电商系统架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# 电商系统负载均衡配置

# Web前端服务器组
upstream web_servers {
least_conn;
server 192.168.1.10:8080 weight=3;
server 192.168.1.11:8080 weight=3;
server 192.168.1.12:8080 weight=2;
}

# API服务器组
upstream api_servers {
ip_hash; # API需要会话保持
server 192.168.1.20:9090;
server 192.168.1.21:9090;
server 192.168.1.22:9090;
}

# 静态资源服务器组
upstream static_servers {
server 192.168.1.30:80;
server 192.168.1.31:80;
}

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

# 静态资源直接代理到静态服务器
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf)$ {
proxy_pass http://static_servers;
expires 30d;
add_header Cache-Control "public, immutable";
}

# API请求
location /api/ {
proxy_pass http://api_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

# 动态页面
location / {
proxy_pass http://web_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

8.2 微服务架构负载均衡

微服务负载均衡配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# 微服务网关配置
upstream user_service {
server 192.168.1.100:8081;
server 192.168.1.101:8081;
}

upstream order_service {
server 192.168.1.102:8082;
server 192.168.1.103:8082;
}

upstream payment_service {
server 192.168.1.104:8083;
server 192.168.1.105:8083;
}

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

# 用户服务
location /api/user/ {
proxy_pass http://user_service;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}

# 订单服务
location /api/order/ {
proxy_pass http://order_service;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}

# 支付服务
location /api/payment/ {
proxy_pass http://payment_service;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}

九、监控与运维

9.1 Nginx状态监控

stub_status模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
server {
listen 80;
server_name status.example.com;

location /nginx_status {
stub_status on;
access_log off;
allow 192.168.1.0/24;
deny all;
}
}

# 访问示例
# curl http://status.example.com/nginx_status

输出示例

1
2
3
4
Active connections: 100
server accepts handled requests
1000 1000 5000
Reading: 0 Writing: 10 Waiting: 90

状态监控脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/bin/bash
# monitor_nginx.sh - Nginx监控脚本

NGINX_STATUS_URL="http://status.example.com/nginx_status"

# 获取状态
status=$(curl -s "$NGINX_STATUS_URL")

# 解析数据
active_conn=$(echo "$status" | grep "Active connections" | awk '{print $3}')
reading=$(echo "$status" | grep "Reading" | awk '{print $2}')
writing=$(echo "$status" | grep "Writing" | awk '{print $4}')
waiting=$(echo "$status" | grep "Waiting" | awk '{print $6}')

echo "=== Nginx状态监控 ==="
echo "活跃连接数: $active_conn"
echo "读取连接数: $reading"
echo "写入连接数: $writing"
echo "等待连接数: $waiting"

# 检查阈值
if [ "$active_conn" -gt 1000 ]; then
echo "警告: 活跃连接数过高"
fi

十、总结

Nginx负载均衡是构建高可用Web架构的核心技术。本文探讨了:

核心要点

  1. 多种负载均衡算法:轮询、加权轮询、IP哈希、最少连接、一致性哈希
  2. 健康检查机制:自动故障检测与恢复
  3. 会话保持方案:IP哈希、Cookie粘性、外部Session存储
  4. 高可用架构:主备Nginx、Keepalived、配置同步

技术栈

  • 负载均衡:upstream、多种算法
  • 健康检查:max_fails、fail_timeout
  • 性能优化:Keepalive、缓冲优化
  • 高可用:Keepalived、主备切换

实践建议

  1. 根据业务特性选择合适的负载均衡算法
  2. 配置健康检查并处理故障
  3. 无状态设计优先,必要时采用Session存储
  4. 实施Nginx集群保障高可用
  5. 监控负载均衡性能与状态

通过合理的负载均衡架构,可构建高可用、高性能的Web服务系统。