Nginx反向代理多IP配置指南?
多IP配置的核心,不在"写进upstream"
很多运维第一次配多IP反向代理,做法是把几个IP写进upstream块,重启,看到流量轮询分发,就认为完成了。但真正上线跑一段时间,问题会陆续冒出来:某台后端挂了,用户还在被轮询到;后端配置不一样,权重没设,高配机器闲着一半;会话没保持,用户刚登录就被分到另一台;后端IP换了,Nginx还在连旧地址。
所以多IP配置的关键,是回答三个问题:流量怎么分(算法)、故障怎么切(健康检查与故障转移)、后端怎么动态更新(服务发现)。下面按这三层展开。
第一层:基础骨架与算法选择
最简结构由upstream和proxy_pass两部分组成。upstream定义后端服务器组,proxy_pass把请求转发到这个组,两者名称必须一致。
upstream backend {
server 192.168.1.101:8080;
server 192.168.1.102:8080;
server 192.168.1.103:8080;
}
不指定策略时默认是轮询,按顺序依次分发。但真实环境里,后端往往不是同规格的,这时要按场景选算法。
加权轮询适合异构集群。高配机器权重设高,低配设低。比如三台机器权重设为5、3、2,流量大致按50%、30%、20%分配。Nginx用的是平滑加权轮询算法,会动态调整,避免高权重节点连续扎堆。
最少连接(least_conn)适合请求耗时差异大的场景。轮询只看请求数量,不看处理时长——一个长任务和一个静态请求在轮询眼里是一样的,容易把某台机器压住。least_conn把新请求发给当前活跃连接最少的服务器,在长连接、耗时不均的应用里更公平。
IP哈希(ip_hash)解决会话保持。如果应用把登录状态、购物车存在服务器本地内存里,用户请求被分到不同机器就会掉登录。ip_hash按客户端IP做哈希,保证同一IP始终落到同一台后端。但要清楚它的局限:一旦某台后端下线,原本指向它的IP会被重新分配到其他节点,会话仍然会丢。所以更稳妥的做法是把会话外置到Redis,而不是依赖ip_hash兜底。
第二层:故障转移与健康检查
这是多IP配置里最容易被忽略、却最决定可用性的一层。
开源版Nginx提供的是被动健康检查,靠两个参数实现:max_fails定义在fail_timeout时间窗口内失败多少次后标记节点不可用,fail_timeout既是统计窗口,也是节点被剔除后的等待时长,超时后重新尝试。默认值是max_fails=1、fail_timeout=10s。
upstream backend {
server 192.168.1.101:8080 max_fails=3 fail_timeout=30s;
server 192.168.1.102:8080 max_fails=3 fail_timeout=30s;
server 192.168.1.103:8080 backup;
}
这里有个细节值得注意:默认情况下,Nginx只把连接错误和超时算作失败。如果后端返回502、504,Nginx不会自动切换。需要显式声明proxy_next_upstream,把http_500、http_502、http_503、http_504纳入触发条件,并用proxy_next_upstream_tries限制重试次数,避免雪崩式重试。
backup参数提供兜底容量。标记为backup的节点不参与正常轮询,只有当所有主节点都不可用时才接管流量。适合放一台配置较低但稳定的灾备机。
主动健康检查需要额外方案。开源版的被动检查有个天然缺陷:只在有请求进来时才检测,空闲时段无法主动剔除故障节点。要主动探测,可以编译淘宝开源的nginx_upstream_check_module模块,支持TCP、HTTP、SSL等多种检查方式;商业版Nginx Plus则内置health_check指令,可配置探测间隔、失败次数、恢复次数和探测URI。
第三层:动态后端与服务发现
后端IP会变的场景(容器化、弹性伸缩、蓝绿发布),写死IP就不行了。
思路是用变量配合resolver。把proxy_pass的目标写成变量形式,Nginx会在运行时重新解析DNS,而不是启动时缓存死。配合resolver指令指定DNS服务器和缓存有效期,就能实现后端变更自动感知。
resolver 8.8.8.8 valid=30s;
upstream backend {
zone backend 64k;
server api.***.com resolve;
}
注意zone指令是Nginx Plus的功能,开源版用于动态配置时需借助第三方模块或外部脚本生成配置后reload。
一个真实案例
某外贸团队用三台服务器做后端,最初只写了三个IP,没配max_fails。某天一台后端因内存溢出被OOM kill,Nginx仍然按轮询把三分之一的请求发给它,用户随机看到502,持续了四十分钟才被发现。
复盘后做了三处调整:给每个节点加上max_fails=3 fail_timeout=30s;增加proxy_next_upstream error timeout http_502 http_503 http_504;补了一台backup节点。同时把日志格式加上$upstream_addr和$upstream_status,方便事后定位是哪台后端出问题。改造后,同样的故障发生时,Nginx在三次失败后自动剔除故障节点,用户无感知。
配置验证与上线习惯
改完配置别直接重启。先用nginx -t测试语法,确认无误再reload(reload比restart平滑,不中断现有连接)。上线后主动验证:连续请求观察节点分布是否符合权重比例;手动停掉一台后端,确认流量自动切换且错误日志记录了节点被标记down;恢复节点后确认流量回流。
另外提醒两点。一是后端地址尽量用内网IP,性能更好也更安全。二是别忘了透传真实客户端信息,配置proxy_set_header X-Real-IP和X-Forwarded-For,否则后端日志里记录的全是代理服务器的IP,排查问题时会抓错重点。
总结
Nginx反向代理多IP配置,完整路径是三层:先用upstream定义后端组,按后端规格和业务特性选择算法(异构用加权轮询、耗时不均用least_conn、需会话保持用ip_hash或外置会话);再配置被动健康检查与故障转移,用max_fails和fail_timeout剔除故障节点,用proxy_next_upstream覆盖HTTP错误码,用backup提供兜底;后端会动态变化的场景,引入resolver实现服务发现。配置完成后务必做故障演练,验证切换逻辑真实生效——没演练过的容灾,等于没有容灾。
纵横云服务器租赁,欢迎随时联系,客服联系方式:QQ3494196421,手机微信19906048601。


