尧图精选

负载均衡从入门到落地:Nginx配置、健康检查与高可用实践

🕒 发布时间:2026/9/7 5:41:19 📁 来源:尧图网络
很多人把负载均衡理解成“加台服务器”这个说法对了一半也很容易让人忽略真正复杂的部分。负载均衡不是简单地把流量拆到两台机器上而是在客户端和后端服务之间加一个调度中枢负责流量接管、节点选择、请求转发、健康检查、故障转移甚至限流和灰度。对刚接触后端运维、自己搭过几台机器但没系统梳理过 Nginx、HAProxy、云负载均衡原理的人来说理解这一层非常关键。下面按实际落地顺序拆先纠正误解再讲四层七层和常见形态然后搭一套最小负载均衡实验接着讲算法和参数再做验证和故障演练最后说清楚常见坑点和高可用边界。1. 先纠正一个误解负载均衡不是“多一台机器”这么简单1.1 加一台服务器只是把单点变成了两个点如果一个网站只有一台服务器请求一多这台机器无论是 CPU、内存、连接数还是带宽都有上限。直观反应是加一台服务器。加完之后问题来了用户的请求到底去哪台机器如果两台机器配置不同、负载不同、一个能连数据库一个连不上分配乱套的风险很大。更重要的是如果其中一台在凌晨挂了系统并不会自动把所有流量切到另一台。除非中间有一个组件能实时判断“哪台机器还活着哪台机器不能给流量”。这个组件就是负载均衡要做的事。所以“加台服务器”只是硬件层面的扩容动作负载均衡更像是给这套扩容动作装上大脑和开关。1.2 负载均衡的本质流量入口和调度中枢负载均衡通常部署在客户端和后端服务之间对外暴露一个统一入口对内管理一组后端节点。它最少承担五件事接收请求客户端不需要知道后端到底有几台只需要访问 LB 的地址。选择节点根据配置的算法从可用节点里挑一台。健康检查定期或按触发条件判断节点是否可用。请求转发把请求转给选中的节点再把响应返回给客户端。故障转移发现节点不可用时尝试把请求交给其他可用节点。把负载均衡想成“门卫加调度员加监控器”会更直观。它不是在停车场旁边再划一个车位而是决定哪辆车进哪个车位、哪个车位坏了不许进。1.3 要解决的四个核心问题可用性、吞吐量、可扩展性、故障恢复负载均衡通常和服务器集群搭配出现但集群只是后端节点的集合LB 才是入口调度。它真正要解决的是四个问题可用性单点故障是系统最大的风险之一负载均衡让流量可以绕开坏掉的节点。吞吐量单台服务器有连接数、CPU、内存、带宽的上限把请求分散到多台服务器后系统整体容量才能扩展。可扩展性如果策略合理新增节点后无需改客户端LB 自动把流量分过去。故障恢复节点恢复后健康检查通过流量又能重新回流。理解这四点之后再看 Nginx upstream 配置、云 SLB 计费项、Keepalived VIP思路会清晰很多。2. 负载均衡工作在哪一层四层、七层和常见形态2.1 四层和七层到底差在哪在 TCP/IP 协议栈里四层指的是传输层主要根据 IP 和端口转发七层是应用层可以解析 HTTP、HTTPS 等协议内容。理解这个区别才知道为什么有的负载均衡方案看起来很“快”却不能按 URL 做路由。对比项四层负载均衡七层负载均衡工作层级传输层IP 端口应用层HTTP/HTTPS能看到的内容源 IP、目标 IP、端口域名、URL 路径、Header、Cookie典型场景数据库主从、长连接、游戏服务Web 服务、接口网关、微服务路由转发方式转发数据包或 TCP 流解析并代理应用请求特点字节级转发吞吐较高控制灵活适合精细化分流四层常见方案有 LVS、Nginx 的 stream 模块、HAProxy 的 TCP 模式以及云负载均衡的 TCP/UDP 监听。七层常见方案有 Nginx 的 http 模块、HAProxy 的 HTTP 模式、Traefik以及云负载均衡的 HTTP/HTTPS 监听。2.2 常见形态软件、硬件、DNS、云负载均衡、Service Mesh负载均衡不只有 Nginx 一种形态。软件负载均衡Nginx、HAProxy、LVS、Traefik。自建成本低配置灵活适合大多数业务。硬件负载均衡F5、A10 等。贵但稳定经常出现在金融、电信等对稳定性和性能要求极高的场景。DNS 负载均衡一个域名解析多个 IP客户端随机访问。实现最简单但节点挂了切换依赖 DNS TTL速度很慢。云负载均衡云厂商托管的负载均衡服务自动处理多可用区自带健康检查、证书管理和监控报警。Service Mesh把负载均衡能力下沉到每个服务边上的代理适合微服务网状流量治理。没有唯一的“标准答案”只有场景是否匹配。2.3 先确定自己的场景需要几层个人博客、API 服务用 Nginx 七层足够数据库读写分离、内网 RPC 服务四层更合适微服务网关需要按域名、路径、Header 做精确路由七层是主流如果只是想快速扛住流量且不想维护 LB 本身云 SLB 性价比更高。我见过一些团队业务刚起步就在 Nginx 外面再套一层 LVS最后排障的时候链路长了一倍。先想清楚场景再决定要不要上更复杂的方案。3. 从零搭一套最小负载均衡实验环境、步骤和验证3.1 实验拓扑与前置条件建议准备三台 Linux 机器一台负载均衡入口两台后端节点。如果你只有一台电脑也可以用 Docker 起两个 Nginx 容器模拟后端再用本机的 Nginx 做 LB方向和原理一样。这里用 Nginx 举例因为它最常见配置也容易理解。假设后端节点 IP 是10.0.0.11和10.0.0.12LB 节点是10.0.0.20。部署前先确认防火墙和安全组已经放行对应端口不然流量到不了后端。装 Nginx 的命令根据系统发行版来# Debian / Ubuntu apt update apt install -y nginx # CentOS / RHEL yum install -y nginx如果你机器上已经有 Nginx不要直接覆盖线上配置。建议复制现有配置文件或者把实验配置放到独立的 include 目录里。3.2 后端节点怎么准备两台后端都安装 Nginx并把监听端口改成8080返回内容分别写上serverA和serverB。为什么要改因为做负载均衡实验时你需要确认请求是否真的发到了不同节点。如果后端返回内容一样你很难判断 LB 是否生效。修改后端 Nginx 配置server { listen 8080; server_name localhost; location / { add_header X-Backend-Node serverA; return 200 response from serverA; } }后端 B 就把“serverA”改成“serverB”。之后用 curl 或浏览器访问可以直接看到响应文本或响应头这是最简便的验证方式。3.3 配置负载均衡入口在 LB 节点上新建一个 Nginx 配置文件upstream backend_cluster { server 10.0.0.11:8080; server 10.0.0.12:8080; } server { listen 80; location / { proxy_pass http://backend_cluster; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }为什么一定要传Host和X-Real-IP因为如果不传 Host后端做多站点虚拟主机判断时可能找不到对应域名如果不传 X-Real-IP 和 X-Forwarded-For后端看到的是 LB 的 IP而不是客户端真实 IP。这样日志、统计、风控都会出错。配置完成后先检查语法再重载nginx -t nginx -s reload3.4 先做两条验证再加健康检查验证命令很简单curl http://10.0.0.20/ curl http://10.0.0.20/连续多次访问正常会看到response from serverA和response from serverB交替出现。如果一直只出现一个先看日志不要急着改参数。接下来加健康检查相关配置upstream backend_cluster { server 10.0.0.11:8080 max_fails3 fail_timeout10s; server 10.0.0.12:8080 max_fails3 fail_timeout10s; }max_fails3 fail_timeout10s的含义是10 秒内转发失败 3 次就把该节点暂时标记为不可用过一段时间再重新接收流量。这是 Nginx 自带的被动健康检查。停掉后端 A再连续 curl。正常情况下所有请求都会落到后端 B。启动后端 A过一会儿后它会重新开始分担流量。注意如果业务需要主动健康检查Nginx 默认配置是做不到的。要么用 HAProxy 的check参数要么用带 upstream_health_check 模块的版本要么直接在云负载均衡上配置健康检查路径。4. 负载均衡算法与关键参数不要一上来就把参数拉满4.1 常见算法怎么选负载均衡的算法并不复杂但选错会让整个集群的容量打折。算法行为适用场景轮询依次分发请求后端能力基本一致加权轮询按 weight 比例分配高低配节点混合最少连接分给当前连接数最少的节点请求处理时间差异大IP 哈希相同客户端 IP 尽量分到同一节点本地 Session、简单会话保持一致性哈希按 key 哈希取模且节点增减影响最小缓存、部分状态型服务Nginx upstream 默认就是轮询。后端两台机器配置差不多时轮询最省心。如果一台高配、一台低配给高配节点设置weight2或更高让它能多接一些流量。4.2 会话保持是常见坑点用户登录后如果 Session 存在后端内存里下一次请求被分到另一台登录态就丢了。这是负载均衡接入后最常见的故障之一。解决方案有三个方向后端做会话共享比如把 Session 放到 Redis 里任意节点都能读到。在 LB 层做会话保持通过 Cookie 或 IP 哈希让同一用户尽量访问同一节点。应用层做无状态化把登录信息放进 Token 或 JWT任意节点验证都能通过。我更建议优先做后端 Session 共享或应用无状态化不要只靠 LB 会话保持。因为ip_hash遇到公司出口 IP、校园网出口 IP 这种“多个用户共享一个 IP”的情况会造成节点流量严重倾斜。4.3 超时、重试与连接复用很多 Nginx 性能上不去不是算法问题而是没有做连接复用。每次请求都新建 TCP 连接对后端压力很大。可以在 upstream 里加keepaliveupstream backend_cluster { least_conn; server 10.0.0.11:8080 weight2 max_fails3 fail_timeout10s; server 10.0.0.12:8080 max_fails3 fail_timeout10s; keepalive 32; }对应的 location 里还需要调整 HTTP 版本和 Headerlocation / { proxy_pass http://backend_cluster; proxy_http_version 1.1; proxy_set_header Connection ; }least_conn表示使用最少连接数算法keepalive 32保留最多 32 个空闲连接供后续请求复用。这个组合适合后端请求处理时间差异较大的场景。重试方面也要小心。GET 这类幂等请求失败后重试问题不大但 POST 请求如果后端已经处理完成、只是响应超时重试就可能造成重复下单、重复扣款。如果要做重试先确认后端接口是否支持幂等。注意不要生产环境直接改线上 Nginx 配置。先在开发或预发环境跑通再走配置发布流程。5. 从验证到批量压测怎么判断“真的均衡”5.1 先看日志不要凭感觉配置完成后不要只靠浏览器反复刷新判断。最可靠的方式是看 LB 的 access log。Nginx 的$upstream_addr可以记录实际转发到了哪个后端节点。建议单独配一个日志格式log_format upstreamlog $remote_addr [$time_local] $request $status $upstream_addr; access_log /var/log/nginx/access.log upstreamlog;重载后用 curl 发十几次请求再检查 access.log 中每条记录的 $upstream_addr 分布。如果十次里 A 和 B 各占一半说明基本均衡。这一步是小样本验证先跑一条、再跑一批不要急着压并发。5.2 用小样本跑通再考虑要不要压测压测工具可以用 ab、wrk、hey。以 ab 为例ab -n 10000 -c 100 http://10.0.0.20/注意压测机不要和 LB 或后端放在同一台机器上否则测出来的瓶颈可能是压测机本身的网络栈、文件描述符或 CPU 限制。也不要一上来就-c 10000先小并发看成功率再逐步增加。需要关注的核心指标包括请求失败率平均响应时间p95 和 p99 响应时间两台后端的 CPU、内存占用LB 节点当前连接数和带宽后端是否出现大量 TIME_WAIT 或连接堆积单看 QPS 很容易误判。比如 QPS 很高但 p99 已经从 50ms 涨到 2 秒这种系统稳定性是很差的。5.3 故障演练停掉一台后端再看表现这是最接近生产价值的一步。在测试环境做一次故障演练停掉后端 A。连续请求 LB确认没有大面积 5xx。查看 LB 日志确认请求全部落在后端 B。重新启动后端 A。观察流量是否自动回流到 A。如果停掉 A 之后请求仍然被转发到 A 并出现超时优先按这个顺序排查健康检查配置是否真的生效后端 A 的防火墙或安全组是否把 LB 的探测请求拒掉了LB 所在节点到 A 的网络是否可达超时时间是否设置得太长导致连接一直卡着才失败。故障演练一定要在测试环境或低峰期做不要拿线上流量直接试。6. 负载均衡器本身也是单点高可用怎么做6.1 Keepalived 虚拟 IP 解决 LB 单点问题很多新手搭完一台 Nginx觉得高可用已经解决了。但很快会发现LB 挂了整个系统也完了。负载均衡器自身也是单点。常见做法是部署两台 LB再用一个虚拟 IPVIP对外提供服务。同一时间只有一个节点绑定 VIP主节点挂了备用节点接管 VIP客户端仍然访问同一个 IP感知不到切换。Keepalived 通过 VRRP 协议实现主备切换。最小配置示意如下vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 100 advert_int 1 virtual_ipaddress { 10.0.0.50 } }备用节点基本一样只需要把state改成BACKUPpriority改成 90。两个节点的virtual_router_id必须一致否则无法组成主备关系。注意这个配置只是最小示意。实际落地还要处理防火墙放行 VRRP 协议、组播网络、探活脚本以及切换后的服务检查。不要在没有充分验证的情况下直接套用到生产环境。6.2 自建和云负载均衡怎么选自建 Nginx Keepalived可控性强配置灵活但证书管理、日志、报警、版本升级都要自己处理。云 SLB 或者 CLB免运维自带健康检查、证书托管、监控报警和多可用区容灾只是配置自由度受平台限制。如果是一个新项目团队人力有限我更建议优先用云负载均衡。如果你所在环境必须内网自建或者已经有大量 Nginx 配置迁移成本太高Keepalived Nginx 完全合理。还有一个容易被忽略的点如果你的应用只有一台后端且能接受比较短的宕机时间可以先不引入负载均衡。先把服务的优雅关闭、日志、监控做扎实比堆一套复杂度更划算。7. 常见坑点与排查链路7.1 坑点配了轮询但请求总是打在同一台先不要怀疑配置。用 curl 连续访问排除浏览器缓存。再看 upstream 里是否开了ip_hash或 Cookie 会话保持。最后看 LB 日志确认每次请求实际转到了哪个后端。如果后端返回了 302 跳转客户端也可能被引导到固定地址导致看起来“总访问同一台”。7.2 坑点后端拿不到客户端真实 IP如果 LB 没有传X-Forwarded-For后端的 access log 里全是 LB 的 IP。日志、统计、限流全部会错。处理方式是在 Nginx location 里补上proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;还要检查后端服务是否正确解析了X-Forwarded-For。很多框架默认看的是X-Real-IP或 remote_addr字段没对上照样拿不到真实 IP。7.3 坑点健康检查一直失败常见原因有以下几种健康检查请求的路径写错后端实际接口是/healthz但 LB 配置成/。后端限制来源 IP 白名单把 LB 节点 IP 漏掉了。后端要求特定 Host 或 HeaderLB 探测请求没有带上。健康检查端口和后端服务端口不一致。后端业务没挂但依赖的数据库或缓存连不上健康检查接口直接返回 5xx。排查顺序是先手动 curl 健康检查地址再带上必要的 Header 重试最后看后端日志里有没有收到来自 LB 的探测请求。7.4 坑点流量仍然分给已经挂掉的节点出现这种情况可能是被动健康检查要等请求失败到次数后才踢掉节点周期比较长也有可能是连接长时间没断超时时间设置太长。处理思路是调短超时、开启主动健康检查、优化后端慢请求处理逻辑。7.5 面向实际场景的排查链路遇到“负载均衡没生效”“经常 5xx”“流量倾斜”这类问题我一般按这个顺序过一遍现象是全部 5xx还是部分 5xx是特别慢还是登录态丢输入请求 URL、路径、Header、Cookie、请求体是否都符合预期。环境LB 与后端的网络是否通防火墙或安全组是否放行DNS 解析是否正常。参数upstream 算法、超时、keepalive、健康检查、重试策略是否合理。工具看nginx -t、access.log、error.log用curl -v看完整请求和响应用ss -lntp查端口监听。大部分“负载均衡没生效”的问题不是 LB 能力不行而是这五步里某一步没有对齐。负载均衡听起来像是“加台服务器”真正落地却是一套关于流量如何接入、如何分配、如何保护和如何恢复的机制。我不建议一开始就把架构堆得很复杂。先把“一个 LB 入口 两台后端 最基本的健康检查 日志验证”跑稳再逐步加上会话保持、Keepalived 高可用、限流和灰度发布。到这一步你再去看 Nginx、HAProxy、云 SLB 还是 Service Mesh就会明白他们到底在解决什么问题。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →