微信优化

weixinyouhua

nginx配置upstream如何实现负载均衡,nginx负载均衡配置详解

2026-09-14 09:12:36

nginx配置upstream的核心答案是:在http块内用upstream指令声明一组后端服务器,再通过server内部的proxy_pass转发到该分组,即可实现负载均衡,Nginx默认按加权轮询分发流量,配合健康检查参数和合理的策略选择,能解决绝大多数高可用场景需求。

nginx upstream配置详解:先把最小可用配置跑起来

初见upstream会有点绕,因为它的配置结构分成两段,第一段定义“后端池子”,放在http块里,跟server块平级,第二段是使用池子,放在location里用proxy_pass指向池子名称。

以下是最小可用的完整配置示例:

http {
    upstream backend {
        server 192.168.1.10:8080;
        server 192.168.1.11:8080;
    }
    server {
        listen 80;
        location / {
            proxy_pass http://backend;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
}

这段配置做的事情很直白:当Nginx收到请求后,会根据upstream里的服务器列表,把请求转发给其中一台后端服务器。

upstream块里每个参数都是干什么的

upstream内部的server指令远比看起来复杂,它支持多个参数,按使用频率排列:

  • weight:加权轮询权重,默认都是1,比如机器A性能是机器B的两倍,可以给A配weight=2,B保持默认。
  • max_fails:允许请求失败的次数,配合超时时间使用,默认1,设为0表示不检查。
  • fail_timeout:max_fails记数的时间窗口,也是节点被标记不可用后的冷却时间,默认10秒。
  • backup:标记为备份服务器,只有当主服务器全部不可用时才接流量。
  • down:标记节点永久下线,常用于灰度发布场景。

一个比较实用的配置时机:在业务高峰期前,如果后端某台机器维护升级,把对应server加个down标记然后reload,比直接改DNS或拔机器安全得多。

nginx upstream轮询和ip_hash区别:选错策略流量会“偏科”

这是配置upstream时最常被问到的问题,也是决定负载是否均匀的关键。

轮询:默认策略,雨露均沾

nginx配置upstream如何实现负载均衡,nginx负载均衡配置详解

加权轮询是Nginx的默认行为,每个请求按权重轮流分发,后端机器接收到的请求数量大致保持均衡。

适合场景:后端服务器状态基本无状态,比如纯API服务、静态资源服务器。

ip_hash:同一用户粘在同一个节点

ip_hash基于客户端IP计算哈希值,将请求固定分配到某台后端服务器,这样同一IP的请求总是打到同一台机器上,保证会话连续性。

upstream backend {
    ip_hash;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}

代价也很明显:如果某台后端宕机,对应落在它上面的IP会被重新哈希到其他节点,但哈希算法基于IP分布,节点数变化会造成相当一部分请求重新映射,建议只在需要session保持的场景使用。

least_conn:谁闲着就把请求给谁

least_conn看后端当前活跃连接数,把新请求分给连接数最少的节点,适合请求处理时间差异较大的场景,比如某些接口响应快、某些接口响应慢。

策略 配法 适用场景 注意点
加权轮询 默认 无状态API 节点性能不均时设weight
ip_hash ip_hash; 有session的Web应用 节点扩容会影响映射
least_conn least_conn; 长连接、响应时长差异大 需要开启keepalive配合
url_hash hash $request_uri; 缓存命中率优先 需要hash key不变化

url_hash是按请求URI做哈希,同一个URL固定落在同一个后端节点,对本地缓存类服务非常友好,行业共识认为,没有通用的最优策略,只能根据业务特性试出来的最合适。

nginx upstream健康检查配置:别让故障节点拖垮整个集群

upstream配置完成后,很多人的第一反应是“这就完了?”默认行为里后端服务器只要被标记为不可用,Nginx会直接跳过它,这是好的一面,但真正的问题在于Nginx如何判断后端已经不可用?

nginx配置upstream如何实现负载均衡,nginx负载均衡配置详解

被动健康检查:开源版默认的保底机制

开源版Nginx本身不具备主动探测能力,它做的是被动检查:请求转发到后端失败或超时之后,Nginx才开始记数。

upstream backend {
    server 192.168.1.10:8080 max_fails=3 fail_timeout=30s;
    server 192.168.1.11:8080 max_fails=3 fail_timeout=30s;
}
location / {
    proxy_next_upstream error timeout http_502 http_503;
}

proxy_next_upstream是关键,它告诉Nginx在哪些情况下应该尝试下一台后端,这行配置意味着:如果当前后端抛错或超时,Nginx自动把请求转给upstream组里的下一台服务器。不配置这个指令,请求失败就直接返回502,不会做任何重试。

主动健康检查:商业版与OpenResty的玩法

Nginx Plus提供主动健康检查,能定期探测后端端口或URL,提前摘除故障节点,开源版想实现类似效果,有两条路:

  • 使用OpenResty(Nginx加Lua扩展)自建探测逻辑。
  • 配合Consul、etcd等注册中心,由外部系统定期更新Nginx upstream列表。

近年来,搭配注册中心动态更新upstream的做法越来越普遍,尤其是容器化环境里节点频繁变化,纯粹手工维护server列表根本忙不过来。

场景实战:nginx配置upstream不生效?多半是这四处细节

upstream配置看起来简单,实际踩坑的人很多,结合常见报错场景,做一个排查清单:

proxy_pass的坑:别把URL路径和upstream名混在一起

nginx upstream配置常见误区之一是proxy_pass末尾多了一个斜杠,或者写在upstream后面跟了完整URL路径。

正确写法:

location /api/ {
    proxy_pass http://backend;
}

注意proxy_pass后没有斜杠,这样Nginx会把完整的原始URI传给后端,如果写成proxy_pass http://backend/;,则会影响路径传递方式,容易导致后端路由404。

不要把upstream名字当域名用,有人写成proxy_pass http://backend:8080;,但backend并不是实际域名,这会导致无法解析。

upstream位置放错

nginx配置upstream如何实现负载均衡,nginx负载均衡配置详解

upstream块必须放在http上下文内,不能写在server块或location块里,如果配置文件里出现“upstream directive is not allowed here”报错,基本都是这个原因。

reload和restart的差别

修改upstream配置后,执行nginx -s reload是平滑加载新配置,不会中断请求。执行restart会造成连接断开,生产环境务必用reload。

与容器化环境配合的坑

当后端是Docker容器时,upstream里的IP不能写容器内部IP,而要写宿主机端口映射后的地址,或使用docker network内可访问的容器名,业务稍微复杂一些的,直接上Consul做服务发现更省心。

nginx配置upstream常见问题解答

为什么我配置了upstream但请求还是固定打到同一条后端?

先检查是否用了ip_hash策略,如果用的是默认轮询,但后端其中一台请求失败率高,连续失败超过max_fails后该节点会被临时移除,流量自然全部打到剩余节点,可以配置max_fails=1 fail_timeout=5s并结合日志确认该节点是否频繁进入冷却状态。

upstream里配置http和https后端能混用吗?

同一upstream组内不建议混用协议,但不同upstream组可以分别配置,转发到HTTPS后端时,proxy_pass写成http://backend即可,Nginx会自动以HTTP方式请求内网后端,如果需要Nginx和后端之间走HTTPS加密,则要配置proxy_ssl_server_name on;和相关证书参数。

长时间运行的WebSocket或大文件上传走upstream会断吗?

会,Nginx默认在60秒内没有数据传输就会断开连接,需要手动调大超时时间,WebSocket场景必须配置proxy_http_version 1.1;加上Upgrade和Connection头,否则WebSocket握手直接失败:

location /ws/ {
    proxy_pass http://backend_ws;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 3600s;
}

最后记住一条核心认知:upstream不是高可用的全部,它负责流量转发,真正保证业务不中断的是健康检查参数、重试机制和节点恢复策略,这三点组合起来才构成完整的nginx配置upstream负载均衡方案。

相关文章

2024年,SaaS软件行业碰到获客难、增长慢等问题吗?

我们努力让每一次邂逅总能超越期待