Java高级后端 · 全套面试通关手册(Nginx)

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 节点配置高频考点)

  1. backup:备份机。所有主节点全部挂掉,才启用 backup 节点。

  2. down:标记节点永久下线,不接收流量。

  3. max_fails:最大失败次数;

  4. 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(面试高频)

  1. Master 读取新配置,校验语法。

  2. 启动新 Worker 进程,新 worker 使用新配置处理新请求。

  3. 老 Worker 不再接收新连接,等待已有连接处理完成后优雅退出。 ✅不会中断正在处理的请求,不停机更新配置。

区别:stop 是强制终止,会中断连接。

二、事件驱动:epoll IO 多路复用

  1. Nginx 底层 epoll(Linux)。一个 worker 单线程,可以监听大量 socket 连接。

  2. 原理:把所有连接注册到 epoll,内核通知哪些连接就绪,worker 只处理就绪事件,没有阻塞等待。

  3. 优势:少量线程处理大量并发连接,减少线程上下文切换开销,高并发性能强。

模型对比: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;
}

优点:

  1. 减轻后端 Java 服务器压力,静态请求不打到应用服务;

  2. Nginx 处理静态文件效率远高于 Java;

  3. 静态资源设置 expires,浏览器本地缓存,减少重复请求。

四、反向代理 vs 正向代理

  1. 正向代理:代理客户端,比如翻墙代理。服务器不知道真实客户端是谁。

  2. 反向代理:代理服务端(Nginx),客户端访问 Nginx,Nginx 转发到后端服务;客户端无感知后端真实节点。Nginx 负载均衡就是反向代理。

五、Nginx 常见模块补充

  1. proxy_pass:反向代理转发请求。

  2. rewrite:url 重写、跳转,基于正则。

  3. ssl 模块:https 证书加密。

  4. 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 请求固定打到同一后端。

缺点 & 不适合场景

  1. 内网用户出口 IP 相同,大量用户被分到同一台,流量倾斜;

  2. 后端节点上下线,哈希重新计算,大量用户会话丢失;

  3. CDN 场景,IP 不断变化,失效。

✅面试加分:生产环境不推荐长期依赖 ip_hash,优先 Redis 实现 session 共享。

(4)least_conn 最少连接

适用场景

后端请求处理时长差异大、长连接业务(如 websocket)。哪个机器当前活跃连接少,就转发给谁。

优点:自动避开压力高的节点。

不适合:短连接、请求处理速度基本一致的场景,轮询更简单。

(5)url_hash(第三方模块)

适用场景

静态资源缓存业务,相同资源 URL 固定路由到同一台后端,提升缓存命中率。

不适合:动态接口、URL 随机变化的业务。

✅选型速查表(背诵精简)

  1. 机器性能相近、无会话需求 → 轮询 round-robin

  2. 机器性能不一致 → 加权轮询 weight

  3. 需要会话保持(临时方案) → ip_hash

  4. 长连接 / 请求耗时差异大 → least_conn 最少连接

  5. 静态资源缓存、固定 url 路由 → url_hash

高频深挖面试追问

Q1:项目里你用的是哪种策略,为什么?

参考口述答案: 项目后端服务配置基本一致,采用默认加权轮询。我们没有使用 ip_hash,会话统一放到 Redis 做 session 共享,不依赖 Nginx 做会话保持。加权可以方便后续扩容,新上线机器调低权重灰度放量。

Q2:ip_hash 有什么坑,什么场景不能用?

  1. 公司内网、统一出口 IP,大量用户 IP 一样,流量集中;

  2. 后端节点扩容 / 下线,hash 环重排,用户 session 失效;

  3. CDN 访问,客户端 IP 持续变化,无法绑定。

结论:ip_hash 是临时方案,分布式系统不要依赖它。

Q3:least_conn 适合短连接业务吗?

不太适合。短连接连接快速创建销毁,连接数波动快,轮询足够,least_conn 收益不大。

Q4:如果后端接口响应时间差异巨大,选哪个?

优先 least_conn,把请求分到当前连接数少的节点,防止慢接口堆积连接。

一句话背诵总结

机器性能均等选轮询;性能不同用加权轮询;长连接、请求耗时差异大用最少连接;

静态缓存用 url_hash;ip_hash 仅临时会话保持使用,生产优先 Redis 共享 session,规避 ip_hash 流量倾斜问题。

相关推荐
阿俊-全栈开发1 小时前
LikeShop单商户Java商城如何从容承接高并发流量?
java·开发语言·spring boot·spring·系统架构
Java小白笔记1 小时前
Java 函数式接口1:从无参任务到自定义多参数查询
java·windows·python
天空鸟_时光不老1 小时前
01-我不转Python把AI塞进Java里
java·人工智能·spring boot·后端·spring·spring cloud·架构
vx_Biye_Design1 小时前
flask学生课程笔记共享系统29026-计算机课程设计、毕业设计
java·javascript·spring boot·后端·elasticsearch·flask·课程设计
代码山河2 小时前
JDK、JRE、JVM的区别:一文讲清楚Java运行环境
java·学习·架构·教程·面向对象·项目
考研保研资料分享2 小时前
211工商管理保研北大光华:夏令营笔试、科研面试与人力资源复习经验
面试·职场和发展
深入云栈2 小时前
Netty 4.2.x 源码深度解析 (十七):Channel 底层读写 —— Unsafe 的 I/O 操作内核
java·后端·架构
自然 醒2 小时前
【AI面试题】刷面试题发现了蝌蚪智汇小程序
人工智能·面试·职场和发展
SimonKing2 小时前
Qoder中Qwen3.8-Flash 限时免费使用
java·后端·程序员