Nginx 的 upstream 模块实现负载均衡,用于分发请求到后端多台服务节点,提升并发、实现故障容错。
1.负载均衡策略
一、基础内置策略(5 种)
(1)round-robin 轮询(默认)
-
规则:请求依次轮流分配给每台后端服务器。
-
特点:默认策略;不考虑服务器性能;某台节点慢,会拖慢部分用户请求。
XML
upstream server_pool {
server 127.0.0.1:8080;
server 127.0.0.1:8081;
}
(2)weight 加权轮询
-
规则:给节点配置权重 weight,权重越高,分配请求越多。
-
适用:服务器硬件性能不一致,高配机器承担更多流量。
XML
upstream server_pool {
server 127.0.0.1:8080 weight=3;
server 127.0.0.1:8081 weight=1;
}
(3)ip_hash IP 哈希
-
规则:根据客户端 IP 做 hash 计算,同一个 IP 永远路由到同一台后端节点。
-
适用:会话保持 session 保持,保证同一用户请求固定到一台服务。
-
缺点:
-
IP 变更,会话丢失;
-
后端节点上下线,hash 值重排,大量用户会重新分配;
-
多用户出口 IP 相同(公司内网),流量倾斜。
-
XML
upstream server_pool {
ip_hash;
server 127.0.0.1:8080;
server 127.0.0.1:8081;
}
(4)least_conn 最少连接
-
规则:请求分配给当前活跃连接数最少的后端节点。
-
适用:后端服务器处理能力差异大,长连接场景。
谁当前连接少,就分给谁。
(5)url_hash(第三方模块)
- 根据请求 url 做 hash,相同 url 固定转发同一台机器。 适用:静态资源缓存,同一个资源固定到一台节点。
二、额外参数(upstream 节点配置高频考点)
-
backup:备份机。所有主节点全部挂掉,才启用 backup 节点。 -
down:标记节点永久下线,不接收流量。 -
max_fails:最大失败次数; -
fail_timeout:失败超时时间。连续 max_fails 次失败,Nginx 将节点标记不可用,等待 fail_timeout 时间后再尝试探测。
XML
upstream server_pool {
server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
server 127.0.0.1:8081 backup;
}
三、健康检查
Nginx 原生被动健康检查:请求转发时探测,失败计数;不主动轮询探测。
-
被动:只有流量过来才检测故障节点,无请求无法发现故障。
-
主动健康检查:Nginx Plus 商业版;开源版本一般借助 nginx_upstream_check 模块(第三方)。
四、高频深挖面试题
Q1:ip_hash 和 session 共享怎么选?
ip_hash 简单,但是有缺陷;分布式项目更推荐redis 统一存储 session,不依赖负载均衡做会话保持。
Q2:加权轮询,权重是固定比例吗?
Nginx 加权轮询不是简单按权重平均,是平滑加权算法,避免流量集中突刺。
Q3:backup 节点什么时候生效?
所有主节点标记失败后,backup 才接管流量;只要任意一台主节点恢复,流量切回主节点。
Q4:Nginx 负载均衡四层和七层区别?
-
7 层(http/https):应用层,可解析 url、cookie、header,http 协议;
-
4 层(stream 模块):传输层 TCP/UDP,只转发数据包,不解析 http,性能更高。
Q5:后端节点宕机,Nginx 还会转发请求吗?
达到 max_fails 失败次数后,fail_timeout 窗口内不再转发;超时后重新尝试探测。
一句话背诵总结
Nginx upstream 负载均衡策略:默认轮询;加权轮询按权重分配流量;
ip_hash 实现 IP 绑定会话保持;least_conn 分配给连接最少节点;
支持 backup 备用节点;原生为被动健康检查;7 层解析 http,4 层 TCP 转发性能更高;
分布式系统优先 redis 共享 session,少依赖 ip_hash。
2.Nginx 核心原理(进程模型、动静分离)
Nginx 特点:高性能、高并发,基于epoll IO 多路复用,事件驱动模型。
一、Nginx 进程模型⭐重点
Nginx 多进程模型:Master 主进程 + Worker 工作进程
(1)Master 进程
管理 Worker 进程,不处理业务请求。
作用:读取 / 校验配置文件;接收信号;管理 worker;热加载(reload)、启停服务。
(2)Worker 进程(多 worker)
实际处理客户端请求,每个 worker 是单线程。
worker 数量一般配置等于 CPU 核心数,或 CPU 核心数 * 2,充分利用多核。
多个 worker 之间相互独立,抢占 accept 锁接收连接。
注意:worker 单线程,但是能处理上万连接,靠 epoll 多路复用,不是靠多线程。
(3)缓存进程 Cache Loader / Cache Manager(可选)
Cache Manager:管理磁盘缓存,清理过期缓存
Cache Loader:启动时加载磁盘缓存到内存
热加载 nginx -s reload(面试高频)
-
Master 读取新配置,校验语法。
-
启动新 Worker 进程,新 worker 使用新配置处理新请求。
-
老 Worker 不再接收新连接,等待已有连接处理完成后优雅退出。 ✅不会中断正在处理的请求,不停机更新配置。
区别:stop 是强制终止,会中断连接。
二、事件驱动:epoll IO 多路复用
-
Nginx 底层 epoll(Linux)。一个 worker 单线程,可以监听大量 socket 连接。
-
原理:把所有连接注册到 epoll,内核通知哪些连接就绪,worker 只处理就绪事件,没有阻塞等待。
-
优势:少量线程处理大量并发连接,减少线程上下文切换开销,高并发性能强。
模型对比:BIO 一个连接一个线程;Nginx epoll 单线程管理大量连接。
三、动静分离⭐高频考点
概念
动态资源:后端 Java 服务生成,如接口、jsp、模板页面;
静态资源:图片、css、js、html、字体文件。
动静分离:Nginx 直接拦截静态资源,本地返回;动态请求转发给后端应用服务器。
XML
# 示例配置
location ~* \.(png|jpg|gif|css|js)$ {
root /static;
expires 7d; #缓存7天,浏览器缓存
}
location /api/ {
proxy_pass http://backend_pool;
}
优点:
-
减轻后端 Java 服务器压力,静态请求不打到应用服务;
-
Nginx 处理静态文件效率远高于 Java;
-
静态资源设置 expires,浏览器本地缓存,减少重复请求。
四、反向代理 vs 正向代理
-
正向代理:代理客户端,比如翻墙代理。服务器不知道真实客户端是谁。
-
反向代理:代理服务端(Nginx),客户端访问 Nginx,Nginx 转发到后端服务;客户端无感知后端真实节点。Nginx 负载均衡就是反向代理。
五、Nginx 常见模块补充
-
proxy_pass:反向代理转发请求。
-
rewrite:url 重写、跳转,基于正则。
-
ssl 模块:https 证书加密。
-
gzip 模块:开启压缩,减小传输包体积,提升速度。
高频深挖面试题
Q1:Worker 进程为什么推荐设置等于 CPU 核心数?
Nginx 是 CPU 密集型,worker 单线程。等于核数避免进程切换;设置过多,进程竞争 CPU,上下文切换变多,性能下降。
Q2:reload 会不会丢请求?
正常 reload 不会。老 worker 处理完已有连接再退出;新连接交给新 worker。如果配置错误,reload 失败,继续使用旧配置。
Q3:epoll 水平触发 LT 和边缘触发 ET?
Nginx 默认 ET 边缘触发。只有状态变化时通知一次,需要一次性读完缓冲区,减少事件触发次数,性能更高。
Q4:expires 缓存原理?
添加 Cache-Control 和 Expires 响应头,浏览器一段时间内不再发起请求,直接读本地缓存,减少服务器压力。
Q5:Nginx 的 accept 锁作用?
多个 worker 抢同一个新连接,accept 锁避免 "惊群效应",防止多个 worker 同时唤醒竞争同一个连接,降低 CPU 消耗。
一句话背诵总结
Nginx 采用 Master-Worker 多进程模型,Master 管理进程,Worker 单线程依靠 epoll IO 多路复用处理海量连接;reload 实现优雅热更新;
动静分离让 Nginx 直接返回静态资源,动态请求转发后端;
反向代理隐藏后端节点,负载均衡基于反向代理实现;
worker 数量建议和 CPU 核心匹配,accept 锁解决惊群。
3.如何根据实际情况选择合适的 Nginx 负载均衡策略
核心思路:根据后端机器性能、是否需要会话保持、业务类型(静态 / 动态、长连接)、流量特征选型。
(1)round-robin 默认轮询
适用场景
后端服务器硬件配置差不多、处理能力一致;无会话绑定需求,短连接 HTTP 业务。
优点 :简单,请求均匀分发。 不
适合:机器性能参差不齐;部分接口处理耗时差异大,慢节点会拖用户。
(2)weight 加权轮询(平滑加权)
适用场景
后端服务器配置不一样,高配机器承载更多流量。比如:3 台 8 核,1 台 4 核,给高配更大 weight。
优点:按机器能力分配流量,资源利用率均衡。
不适合:需要同一用户固定访问同一台后端、会话保持场景。
(3)ip_hash
适用场景
需要会话保持,没有搭建分布式 session 共享(临时方案);同一客户端 IP 请求固定打到同一后端。
缺点 & 不适合场景
-
内网用户出口 IP 相同,大量用户被分到同一台,流量倾斜;
-
后端节点上下线,哈希重新计算,大量用户会话丢失;
-
CDN 场景,IP 不断变化,失效。
✅面试加分:生产环境不推荐长期依赖 ip_hash,优先 Redis 实现 session 共享。
(4)least_conn 最少连接
适用场景
后端请求处理时长差异大、长连接业务(如 websocket)。哪个机器当前活跃连接少,就转发给谁。
优点:自动避开压力高的节点。
不适合:短连接、请求处理速度基本一致的场景,轮询更简单。
(5)url_hash(第三方模块)
适用场景
静态资源缓存业务,相同资源 URL 固定路由到同一台后端,提升缓存命中率。
不适合:动态接口、URL 随机变化的业务。
✅选型速查表(背诵精简)
-
机器性能相近、无会话需求 → 轮询 round-robin
-
机器性能不一致 → 加权轮询 weight
-
需要会话保持(临时方案) → ip_hash
-
长连接 / 请求耗时差异大 → least_conn 最少连接
-
静态资源缓存、固定 url 路由 → url_hash
高频深挖面试追问
Q1:项目里你用的是哪种策略,为什么?
参考口述答案: 项目后端服务配置基本一致,采用默认加权轮询。我们没有使用 ip_hash,会话统一放到 Redis 做 session 共享,不依赖 Nginx 做会话保持。加权可以方便后续扩容,新上线机器调低权重灰度放量。
Q2:ip_hash 有什么坑,什么场景不能用?
-
公司内网、统一出口 IP,大量用户 IP 一样,流量集中;
-
后端节点扩容 / 下线,hash 环重排,用户 session 失效;
-
CDN 访问,客户端 IP 持续变化,无法绑定。
结论:ip_hash 是临时方案,分布式系统不要依赖它。
Q3:least_conn 适合短连接业务吗?
不太适合。短连接连接快速创建销毁,连接数波动快,轮询足够,least_conn 收益不大。
Q4:如果后端接口响应时间差异巨大,选哪个?
优先 least_conn,把请求分到当前连接数少的节点,防止慢接口堆积连接。
一句话背诵总结
机器性能均等选轮询;性能不同用加权轮询;长连接、请求耗时差异大用最少连接;
静态缓存用 url_hash;ip_hash 仅临时会话保持使用,生产优先 Redis 共享 session,规避 ip_hash 流量倾斜问题。