news 2026/4/29 11:45:24

还在用单台Nginx扛流量?一文讲透负载均衡+Keepalived高可用方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
还在用单台Nginx扛流量?一文讲透负载均衡+Keepalived高可用方案

为什么需要这篇文档?

很多公司的架构演进会经历这样一个过程:

阶段一:单机部署,nginx+ 后端服务都在一台服务器。某天后端服务挂了,网站打不开;或者流量突增,服务器扛不住了。

阶段二:开始拆分,nginx单独一台,后端多台部署,用 upstream 做负载均衡。解决了单点故障和性能瓶颈,但发现 nginx自己成了新的单点。

阶段三:nginx也做高可用,Keepalived + VIP,主备切换。终于有了完整的高可用架构,但又遇到新问题:切换时连接中断、灰度发布怎么做、如何动态调整后端…

这里不讲零散的概念,看完希望能有以下收获:

  1. 根据业务场景选择合适的负载均衡算法
  2. 设计高可用架构并平滑处理故障切换
  3. 实现灰度发布、蓝绿部署等高级流量治理

1、负载均衡核心原理

1.1 四层负载均衡 vs 七层负载均衡

很多人分不清 nginx的负载均衡工作在哪个层面:

层面协议特点适用场景
四层代理TCP/UDP基于 IP + 端口转发,性能高数据库、Redis、RPC 服务
七层代理HTTP/HTTPS基于 URL/Header/Cookie 转发,功能丰富Web 应用、API 网关

nginx同时支持两者

# 七层负载均衡(HTTP) http { upstream backend { server 10.0.0.1:8080; server 10.0.0.2:8080; } server { listen 80; location / { proxy_pass http://backend; } } } # 四层负载均衡(TCP) stream { upstream mysql_backend { server 10.0.0.1:3306; server 10.0.0.2:3306; } server { listen 3306; proxy_pass mysql_backend; } }

选择建议

  • HTTP/HTTPS 服务用七层,可以基于 URL 做精细化路由
  • 数据库、缓存等 TCP 服务用四层,性能损耗小

1.2 负载均衡算法深度解析

nginx支持多种负载均衡算法,每种都有特定的适用场景:

1.2.1 轮询(round-robin)- 默认算法

upstream backend { server 10.0.0.1:8080 weight=3; # 权重3 server 10.0.0.2:8080 weight=2; # 权重2 server 10.0.0.3:8080 weight=1; # 权重1 # 请求按 3:2:1 的比例分发 }

原理:按照权重轮流分发请求适用:后端服务器配置相同,处理能力不同时用权重调整

优点:简单公平缺点:不考虑后端实际负载

1.2.2 IP哈希(ip_hash)

upstream backend { ip_hash; server 10.0.0.1:8080; server 10.0.0.2:8080; }

原理:对客户端 IP 做哈希计算,相同 IP 永远分配到同一台后端适用:需要会话保持的应用(无共享 session)

优点:解决 session 问题缺点:负载可能不均(某个 IP 段请求多)

高级玩法:用hash指令实现更灵活的会话保持

# 根据请求参数保持会话 upstream backend { hash $arg_session_id consistent; server 10.0.0.1:8080; server 10.0.0.2:8080; } # 根据 cookie 保持会话 upstream backend { hash $cookie_userid consistent; server 10.0.0.1:8080; server 10.0.0.2:8080; }

1.2.3 最少连接(least_conn)

upstream backend { least_conn; server 10.0.0.1:8080; server 10.0.0.2:8080; }

原理:转发给当前活跃连接数最少的后端适用:请求处理时间差异很大的场景(如大文件下载、长轮询)

优点:真正的负载均衡,考虑实际负载缺点:需要维护连接状态

一致性哈希(hash consistent)

upstream backend { hash $request_uri consistent; server 10.0.0.1:8080; server 10.0.0.2:8080; server 10.0.0.3:8080; }

原理:使用一致性哈希算法,节点变化时只影响少量请求适用:缓存服务、分布式存储

优点:扩缩容时缓存命中率高缺点:实现复杂

1.3 负载均衡算法选型矩阵

业务场景推荐算法原因
无状态微服务轮询 + keepalive简单高效
有状态应用(无分布式session)IP哈希保持会话
大文件下载/视频流最少连接避免慢连接堆积
API网关轮询通常无状态
缓存集群一致性哈希扩缩容影响小
gRPC服务最少连接长连接场景

2、健康检查机制

2.1 被动健康检查

被动式、传输层的健康检查(Nginx 原生)。它只能知道后端“连不上”,不知道后端“业务挂了”。

upstream backend { server 10.0.0.1:8080 max_fails=3 fail_timeout=30s; server 10.0.0.2:8080 max_fails=3 fail_timeout=30s; } # nginx 不会主动发请求,当真实用户请求进来,Nginx 尝试连接 10.0.0.1。 # 如果连接失败(拒绝连接、超时)或返回了特定的错误(默认是 502/503/504 等),计数器 +1。 # 当连续失败3次 (max_fails=3),Nginx 将该节点标记为“不可用”,在接下来的30秒(fail_timeout=30s) 内不再转发任何请求给它。 # 30秒后,Nginx 会尝试“试探性”地转发一个新请求给它,如果成功则恢复,失败则重新计时。

2.2 主动健康检查

主动式、应用层的健康检查(需要第三方模块,如nginx_upstream_check_module)。它能真正探测后端业务是否存活。

upstream backend { server 10.0.0.1:8080; server 10.0.0.2:8080; # 主动健康检查 # check interval=3000 rise=2 fall=5 timeout=5000 type=http; check_http_send "HEAD /test/status.jsp HTTP/1.0\r\n\r\n"; check_http_expect_alive http_2xx http_3xx; } # nginx每隔3秒向后端服务器发送一个 HEAD 请求,询问/test/status.jsp。 # 连续 2 次 (rise=2) 收到 2xx 或 3xx 状态码,标记为“健康”。 # 连续 5 次 (fall=5) 超时或状态码不对,标记为“不健康”,立即停止转发流量。

3、高可用架构设计

3.1 为什么要做高可用?

单点故障场景

  • nginx 服务器宕机 → 所有业务中断
  • nginx 进程崩溃 → 服务不可用
  • 机房网络故障 → 区域无法访问

高可用目标

  • 故障自动切换(< 5秒)
  • 数据不丢失
  • 对客户端透明

3.2 Keepalived + Nginx 主备模式

这是最常见的高可用方案:

虚拟IP:192.168.1.100 ↓ ┌────┴───┐ ↓ ↓ Master Backup 192.168.1.10 192.168.1.11 ↓ ↓ Nginx Nginx ↓ ↓ 后端服务 后端服务

3.2.1 Keepalived 配置

主节点配置(/etc/keepalived/keepalived.conf):

global_defs { router_id nginx_master } vrrp_script check_nginx { script "/etc/keepalived/check_nginx.sh" # 检查脚本 interval 2 weight -20 fall 2 rise 1 } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1234 } virtual_ipaddress { 192.168.1.100/24 dev eth0 } track_script { check_nginx } notify_master "/etc/keepalived/master.sh" notify_backup "/etc/keepalived/backup.sh" notify_fault "/etc/keepalived/fault.sh" }

备节点配置

global_defs { router_id nginx_backup } vrrp_script check_nginx { script "/etc/keepalived/check_nginx.sh" interval 2 weight -20 } vrrp_instance VI_1 { state BACKUP interface eth0 virtual_router_id 51 priority 90 # 比主节点低 advert_int 1 authentication { auth_type PASS auth_pass 1234 } virtual_ipaddress { 192.168.1.100/24 dev eth0 } track_script { check_nginx } }

健康检查脚本(/etc/keepalived/check_nginx.sh):

#!/bin/bash # 检查 Nginx 是否存活 if pgrep nginx > /dev/null; then # 再检查端口是否监听 if netstat -tnlp | grep :80 > /dev/null; then exit 0 fi fi # 尝试重启 systemctl restart nginx sleep 2 if pgrep nginx > /dev/null; then exit 0 else exit 1 fi

3.3 注意点:ARP 缓存问题

主备切换后,客户端和交换机的 ARP 缓存可能还是旧 MAC 地址,导致流量依然发往故障节点。

解决方案

# 主节点切换时发送 gratuitous ARP vrrp_instance VI_1 { # ... 其他配置 # 切换时发送 5 个 gratuitous ARP garp_master_delay 5 garp_master_repeat 5 # 主动刷新 ARP notify_master "/etc/keepalived/refresh_arp.sh" } # 【关键参数 1】garp_master_delay 5 # 含义:成为 Master 后,等待 5 秒 再开始发送 ARP 广播。 # 作用:给系统一点时间让网卡完全启动、IP 地址完全绑定好。 # 风险:如果设得太小(如 0),可能 IP 还没绑好就发 ARP,交换机学不到;设得太大,切换延迟增加。 # 建议:通常 2-5 秒是安全的,但在极速切换场景下可改为 0 或 1。 # 【关键参数 2】garp_master_repeat 5 # 含义:连续发送 5 次 免费 ARP (Gratuitous ARP) 包。 # 作用:防止丢包。发一次可能丢了,发 5 次确保交换机一定能收到并更新 MAC 地址表。 # 【关键参数 3】notify_master "/etc/keepalived/refresh_arp.sh" # 含义:当状态变为 MASTER 时,执行这个脚本。 # 作用:执行自定义的“暴力刷新”逻辑,作为内置 ARP 发送的补充。
#!/bin/bash # notify_master.sh - 刷新 ARP 缓存 VIP="192.168.1.100" INTERFACE="eth0" # 记录日志 echo "Keepalived: Becoming MASTER, sending gratuitous ARP for $VIP" # 1. 发送免费 ARP (核心动作) # 循环发送几次,确保交换机收到 for i in {1..5}; do arping -U -I $INTERFACE -c 1 $VIP sleep 0.1 # 间隔 100ms,避免发包太快被交换机限速丢弃 done # 如果确实发现本机访问网关有问题,可以只刷新网关的 ARP exit 0

4、高级流量治理

4.1 灰度发布(金丝雀发布)

场景:新版本只让 10% 的流量验证,没问题再全量。

4.1.1 基于权重

upstream backend { server 10.0.0.1:8080 weight=90; # 旧版本 90% server 10.0.0.2:8080 weight=10; # 新版本 10% }

缺点:权重调整需要 reload,连接会断开

4.1.2 基于 Cookie/Header

http { upstream new_backend { server 10.0.0.1:8080; } upstream old_backend { server 10.0.0.2:8080; } # 假设 cookie 名为 "user_id" split_clients "${cookie_user_id}" $variant_ratio { 10% "new"; * "old"; } # 或者使用其他标识,比如 IP 地址 # split_clients "$remote_addr" $variant_ratio { # 10% "new"; # * "old"; # } # 根据 header 覆盖灰度结果 map $http_canary $final_variant { default $variant_ratio; "enable" "new"; } map $final_variant $upstream_name { "new" "new_backend"; "old" "old_backend"; } server { listen 80; location / { proxy_pass http://$upstream_name; } } }

4.1.3基于 IP 段(内测用户优先)

geo $canary_group { default 0; 10.0.0.0/8 1; # 内网IP 192.168.1.0/24 1; # 公司IP段 114.212.33.0/24 1; # 特定外网IP } upstream backend { server 10.0.0.1:8080; # 旧版本 } upstream backend_canary { server 10.0.0.2:8080; # 新版本 } location / { if ($canary_group = 1) { proxy_pass http://backend_canary; break; } proxy_pass http://backend; }

4.2 蓝绿部署

原理:两套环境(蓝和绿),通过切换流量实现无缝发布。

# 初始状态:蓝环境在线 upstream backend { server blue:8080; # 当前生产 server green:8080 down; # 备用 } # 部署新版本到 green # 测试验证后,切换流量 upstream backend { server blue:8080 down; # 下线蓝 server green:8080; # 上线绿 } # 切换只需要 reload,秒级完成 nginx -s reload # 有状态应用:如果用户的 Session 存储在 Blue 服务器的内存中,切换后用户跳转到 Green,会立即掉线(需要重新登录) # 共享会话:必须使用 Redis/Memcached 等外部存储共享 Session,不能存本地内存。

4.3 A/B 测试

原理:利用 IP 算出一个固定的“标签”,再把“标签”翻译成“服务器组名”,最后让 nginx根据这个名字动态把请求扔过去。

http { upstream backend_v1 { server 10.0.0.1:8080; } upstream backend_v2 { server 10.0.0.2:8080; } # 基于 IP 分流 split_clients "$remote_addr" $ui_version { 50% "v2"; * "v1"; } # 使用 map 将版本映射到 upstream 名称 map $ui_version $backend_name { "v2" "backend_v2"; "v1" "backend_v1"; default "backend_v1"; # 防御性默认值 } server { listen 80; location / { proxy_pass http://$backend_name; # 添加调试头 add_header X-UI-Version $ui_version; add_header X-Backend $backend_name; # 标准 proxy 设置 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } }

5、生产环境最佳实践

5.1 架构选型矩阵

规模节点数负载均衡高可用方案upstream管理
初创期1静态配置
成长期2-5nginx upstreamKeepalived主备静态配置
发展期5-20nginx + LVSKeepalived双主脚本动态更新
成熟期20-100+多层负载均衡DNS轮询+多活Consul + nginx-upsync

5.2 配置规范

upstream 命名规范

upstream service-product {} # 业务服务名 upstream service-order {} upstream service-user {} upstream gateway-api {} # API网关 upstream static-assets {} # 静态资源

server 标签规范

server 10.0.0.1:8080 weight=5 max_fails=3 fail_timeout=30s; # 生产 server 10.0.0.2:8080 backup; # 备用 server 10.0.1.1:8080 down; # 已下线

5.3 容量规划

# 单机预估容量 worker_processes auto; # 通常等于 CPU 核心数 worker_connections 65535; # 每个 worker 最大连接数 # 理论最大并发连接数 = worker_processes * worker_connections # 例如:8核 * 65535 ≈ 50万并发连接 # 实际建议水位:最大值的 60-70% # 8核 * 65535 * 0.7 ≈ 35万连接

负载均衡和高可用不是一蹴而就的,而是一个持续演进的过程:

  1. 阶段一:先做负载均衡,解决单点性能瓶颈
  2. 阶段二:再做高可用,解决 nginx 自身单点
  3. 阶段三:灰度发布,提升发布效率
  4. 阶段四:多活架构,实现真正的弹性伸缩
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/29 11:43:35

如何快速掌握二维码修复:QrazyBox的完整使用指南

如何快速掌握二维码修复&#xff1a;QrazyBox的完整使用指南 【免费下载链接】qrazybox QR Code Analysis and Recovery Toolkit 项目地址: https://gitcode.com/gh_mirrors/qr/qrazybox 你是否遇到过打印的会议二维码模糊不清&#xff0c;手机拍摄的电子票二维码被水渍…

作者头像 李华
网站建设 2026/4/29 11:43:34

Promise错误处理完全手册:catch与onRejected的深度解析

Promise错误处理完全手册&#xff1a;catch与onRejected的深度解析 【免费下载链接】promises-book JavaScript Promise迷你书 项目地址: https://gitcode.com/gh_mirrors/pro/promises-book JavaScript Promise迷你书是学习Promise编程的重要资源&#xff0c;它系统讲解…

作者头像 李华
网站建设 2026/4/29 11:39:22

3种场景下的GPU内存故障诊断:MemtestCL专业级解决方案深度解析

3种场景下的GPU内存故障诊断&#xff1a;MemtestCL专业级解决方案深度解析 【免费下载链接】memtestCL OpenCL memory tester for GPUs 项目地址: https://gitcode.com/gh_mirrors/me/memtestCL 您是否曾遇到GPU计算任务突然崩溃、深度学习训练意外中断或游戏画面频繁闪…

作者头像 李华
网站建设 2026/4/29 11:37:43

5步部署CosyVoice-300M Lite:打造你的专属语音合成服务

5步部署CosyVoice-300M Lite&#xff1a;打造你的专属语音合成服务 1. 引言 1.1 语音合成的价值与应用 语音合成技术正在改变我们与数字世界的交互方式。从智能客服的自动应答&#xff0c;到有声读物的自动生成&#xff0c;再到各类语音助手的自然对话&#xff0c;高质量的文…

作者头像 李华