Nginx默认轮询是确定性循环链表遍历,按upstream中server书写顺序用内部指针逐台分发请求,到末尾回绕;weight、ip_hash、健康参数不一致等配置会干扰均匀性,需清理冗余并统一配置方可保障长期均衡。

nginx 负载均衡的轮询模式默认按 upstream 块中 server 的书写顺序,用一个内部指针逐台分发请求,到末尾自动回绕——它不看响应快慢、不比连接数、也不依赖时间或随机数,只严格“点名”。
轮询是怎么一步步分发请求的
本质是一个确定性的循环链表遍历过程,每来一个请求就推进一次指针:
- 第 1 个请求 → 发给 upstream 列表里第 1 行的 server(指针初始位置)
- 第 2 个请求 → 指针下移,发给第 2 行的 server
- 第 3 个请求 → 指针再下移,发给第 3 行的 server
- 第 4 个请求 → 列表已到底,指针归零,重新发给第 1 行的 server
哪些配置会干扰默认轮询的均匀性
轮询本身很守规矩,但以下配置会让它“没法按规矩办事”:
- 某行 server 含 weight= 参数 → 立刻退化为加权轮询,不再是均等分配
- upstream 块顶部写了 ip_hash 或 hash $request_uri → 请求被固定路由,轮询完全失效
- 某台 server 配了 max_fails 和 fail_timeout,而其他没配 → 健康检查阈值不一致,故障剔除不同步,导致轮询队列动态变短
让轮询真正保持均匀的关键操作
重点不是加功能,而是清理和对齐:
- 删掉所有 server 行里的 weight=,确保每行都是裸 IP 或域名,如 server 10.0.1.10;
- 确认 upstream 块开头没有 ip_hash、least_conn、hash 等指令,整行删除,不要只注释
- 给每台 server 显式配一致的健康探测:比如统一写 max_fails=2 fail_timeout=15s
- 用 $upstream_addr 记入 access_log,直接看日志验证实际落到哪台,比猜测更可靠
轮询适合什么场景,又不适合什么
它不是万能解法,但非常适合作为起点:
- 适合:后端服务器性能接近、处理耗时相对稳定、无状态服务、新上线或灰度阶段
- 不适合:服务器 CPU/内存负载差异大、长连接占比高、需要会话保持、或响应时间波动剧烈的业务


















