Nginx 与负载均衡
Nginx 是最常见的反向代理和七层负载均衡器,LVS 是 Linux 内核中的四层负载均衡。大型站点的入口通常是“LVS 加 Keepalived 做四层,Nginx 做七层,再转发给应用”。面试中常问 Nginx 为什么能支撑高并发、负载均衡有哪些算法、四层和七层有什么区别、LVS 的几种模式,以及 502 和 504 怎样排查。
1. 面试核心
先记住这几条,再读正文- Nginx 是一个 master 进程加多个 worker 进程的结构,每个 worker 单线程运行事件循环,用 epoll 同时处理大量非阻塞连接,不为每个连接创建线程,所以内存占用小、并发能力高。卡 · Nginx 的结构与常用配置
- 常用功能:反向代理、负载均衡、静态文件服务(动静分离)、TLS 终止、缓存、限流、按域名和路径路由。
- 四层负载均衡(LVS)按 IP 和端口转发,不解析应用协议,性能高;七层(Nginx)解析 HTTP,能按 URL、Header 路由,能改写请求,但开销更大。LVS 有 NAT、DR、TUN 等模式,DR 模式响应直接返回客户端,性能最好。卡 · 负载均衡
- Nginx 的负载均衡算法有加权轮询(默认)、最少连接、IP 哈希和一致性哈希;开源版通过失败次数做被动健康检查。
- 502 表示 Nginx 从上游得到无效响应或连不上上游(进程挂了、端口没监听、连接被重置);504 表示上游在超时时间内没有响应(处理慢、下游慢)。先看 Nginx 错误日志,再看上游的状态和日志。卡 · 502 与 504
2. Nginx 的结构与常用配置
进程模型:master 进程读取配置、管理 worker;worker 进程处理请求,数量一般等于 CPU 核数。每个 worker 用 epoll 监听大量连接,哪个连接有事件就处理哪个,处理过程中不阻塞。修改配置后执行 nginx -s reload,master 启动新的 worker,旧 worker 处理完已有请求后退出,实现不中断地重载。
与 Apache 的对比:Apache 的传统模式(prefork、worker)为每个连接分配一个进程或线程,连接多时内存和上下文切换开销大;Nginx 用少量 worker 处理大量连接,适合高并发和反向代理。Apache 的模块生态丰富,.htaccess 支持按目录配置;现在 Apache 也有基于事件的 MPM。
upstream backend {
least_conn;
server 10.0.0.11:8080 weight=2 max_fails=3 fail_timeout=10s;
server 10.0.0.12:8080;
keepalive 64; # 与上游保持的空闲长连接
}
server {
listen 443 ssl;
server_name example.com;
location /static/ { # 动静分离:静态文件由 Nginx 直接返回
root /data/www;
expires 7d;
}
location /api/ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection ""; # 配合 keepalive 复用上游连接
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 3s;
proxy_read_timeout 30s;
}
}
3. 负载均衡
Nginx 的算法
| 算法 | 配置 | 适用 |
|---|---|---|
| 加权轮询 | 默认,weight 设置权重 | 后端处理能力相近、请求耗时相近 |
| 最少连接 | least_conn | 请求耗时差别大 |
| IP 哈希 | ip_hash | 同一客户端落到同一后端(会话保持),但客户端在 NAT 后会导致不均 |
| 一致性哈希 | hash $request_uri consistent | 按 URL 等键固定后端,后端增减时只影响少量键,适合缓存 |
健康检查:开源版是被动检查,某个后端在 fail_timeout 时间内失败 max_fails 次,就在这段时间内不再转发给它;主动探测需要商业版或第三方模块。
四层与七层
| 维度 | 四层(LVS、云负载均衡的 TCP 监听) | 七层(Nginx、HAProxy、Envoy) |
|---|---|---|
| 依据 | IP 和端口 | HTTP 的 URL、Host、Header、Cookie |
| 能力 | 只转发,不理解请求内容 | 路由、改写、TLS 终止、缓存、限流、重试 |
| 性能 | 高,LVS 在内核中转发 | 较低,需要在用户态解析协议 |
| 连接 | 客户端与后端之间是同一条 TCP 连接(NAT、DR 模式) | 客户端到代理、代理到后端是两条连接 |
LVS 的模式
| 模式 | 做法 | 特点 |
|---|---|---|
| NAT | 改写目的 IP 转给后端,响应也经过 LVS 改回源地址 | 配置简单;请求和响应都经过 LVS,容易成为瓶颈;后端网关要指向 LVS |
| DR | 只改写目的 MAC,后端在回环接口上配置 VIP,直接把响应发给客户端 | 性能最好;LVS 与后端必须在同一二层网络,后端要抑制对 VIP 的 ARP 响应 |
| TUN | 用 IP 隧道封装后转发,后端解封装后直接响应客户端 | 可以跨网段;后端需要支持隧道 |
| FULLNAT | 同时改写源和目的地址 | 可以跨网段部署,后端通过 TOA 等方式获取客户端真实 IP |
Keepalived:用 VRRP 协议在主备两台负载均衡器之间漂移虚拟 IP,主节点故障时备节点接管 VIP;同时对后端做健康检查,自动维护 LVS 的后端列表。
4. 502 与 504
| 状态码 | 产生方 | 含义 | 常见原因 |
|---|---|---|---|
| 500 | 应用 | 应用内部错误 | 代码异常 |
| 502 Bad Gateway | Nginx | 连不上上游,或上游返回了无效响应 | 上游进程挂了、端口没有监听、连接被拒绝或重置;上游主动关闭了 Nginx 正在复用的长连接;响应头过大 |
| 503 | Nginx 或应用 | 服务暂不可用 | 所有上游都被标记为不可用、触发限流 |
| 504 Gateway Timeout | Nginx | 上游在超时时间内没有返回 | 应用处理慢、数据库慢查询、下游依赖超时、线程池耗尽 |
| 499 | Nginx 日志 | 客户端在响应返回前断开了连接 | 客户端超时短于服务端处理时间 |
排查步骤:
- 看 Nginx 的
error.log,错误信息直接说明原因:connect() failed (111: Connection refused)表示上游没监听,upstream prematurely closed connection表示上游提前关闭,upstream timed out表示超时。 - 看访问日志中的
$upstream_addr、$upstream_status、$upstream_response_time,确定是哪个上游、耗时多少,是否集中在某一台。 - 到对应的上游检查:进程是否存活、端口是否监听(
ss -lntp)、应用日志、线程池和连接池、GC;504 还要沿调用链查慢在哪里。 - 检查配置:超时时间是否合理,上游长连接的空闲超时是否短于应用侧,避免复用已被关闭的连接。
5 · 面试题卡片
5.1 Nginx 有什么作用?它为什么能支撑很高的并发?与 Apache 有什么区别?
出现公司:虾皮、小米、美团、BIGO、网易游戏
考察重点
- master/worker 进程模型与 epoll 事件驱动。
- 常用功能与动静分离;与 Apache 连接模型的差异。
相关内容:Nginx 的结构与常用配置、I/O 多路复用。
参考回答
Nginx 常用于反向代理和负载均衡、静态文件服务、TLS 终止、缓存、限流,以及按域名和路径把请求路由到不同的后端。动静分离就是用 location 区分路径,静态文件由 Nginx 直接从磁盘返回,动态请求通过 proxy_pass 转给应用。
高并发来自它的结构:一个 master 进程管理若干 worker,worker 数量通常等于 CPU 核数;每个 worker 是单线程的事件循环,用 epoll 同时监听成千上万个非阻塞连接,只处理已经就绪的事件,等待 I/O 时不占用线程。连接数增加时不会增加进程或线程,内存占用和上下文切换都很少。配置重载时 master 启动新 worker,旧 worker 处理完已有请求再退出,服务不中断。
Apache 的传统模式为每个连接分配一个进程或线程,并发高时资源消耗大;它的优势是模块生态丰富、支持 .htaccess 按目录配置、对动态模块的支持成熟。现在 Apache 也有事件驱动的 MPM,但高并发的反向代理场景仍以 Nginx 为主。
5.2 四层负载均衡和七层负载均衡有什么区别?Nginx 和 LVS 怎样选择?LVS 有哪几种模式?
出现公司:小米、网易互娱、网易、虾皮、美团、BIGO
考察重点
- 四层与七层的依据、能力和性能差异;Nginx 的负载均衡算法。
- LVS 各模式的报文路径与限制;Keepalived 的 VRRP。
参考回答
四层负载均衡只看 IP 和端口,按连接转发,不解析应用协议,LVS 在内核中完成转发,性能很高;七层负载均衡解析 HTTP,能按域名、URL、Header 路由,能做 TLS 终止、改写请求、缓存和重试,但要在用户态解析协议,开销更大,客户端到代理和代理到后端是两条连接。常见的组合是入口用 LVS 加 Keepalived 承担大流量的四层分发,后面接多台 Nginx 做七层路由。Nginx 的算法有加权轮询、最少连接、IP 哈希和一致性哈希,开源版通过 max_fails 做被动健康检查。
LVS 的模式:NAT 模式改写目的 IP 转给后端,响应也要经过 LVS 改回,LVS 容易成为瓶颈;DR 模式只改写目的 MAC,后端在回环接口上配置 VIP 并抑制对 VIP 的 ARP 响应,响应直接返回客户端,性能最好,但要求 LVS 和后端在同一个二层网络;TUN 模式用 IP 隧道封装,后端解封装后直接响应,可以跨网段;FULLNAT 同时改写源和目的地址,可以跨网段,后端通过 TOA 等方式取得客户端真实 IP。
Keepalived 用 VRRP 协议让主备两台负载均衡器共享一个虚拟 IP,主节点定期发送通告,备节点收不到时接管 VIP;它还对后端做健康检查,自动从 LVS 中摘除故障节点。
5.3 Nginx 返回 502 和 504 分别是什么原因?怎样排查?和 500 有什么区别?
出现公司:杭州观远数据、美团
考察重点
- 状态码由谁产生;502 与 504 的典型原因。
- 从 Nginx 错误日志和上游字段定位到具体后端;长连接复用导致的 502。
相关内容:502 与 504、Linux 网络排查。
参考回答
500 是应用自己返回的内部错误。502 和 504 是 Nginx 作为网关产生的:502 表示 Nginx 连不上上游,或者上游返回了无效的响应,常见原因是上游进程挂了、端口没有监听、连接被拒绝或重置,还有一种是 Nginx 复用了上游已经关闭的长连接;504 表示上游在 proxy_read_timeout 时间内没有返回,原因是应用处理慢、数据库慢查询、下游依赖超时或线程池耗尽。
排查时先看 Nginx 的 error.log,信息很直接:Connection refused 说明上游没有监听,upstream prematurely closed connection 说明上游提前断开,upstream timed out 说明超时。再看访问日志中的 $upstream_addr、$upstream_status 和 $upstream_response_time,确认是哪一台上游、耗时多少、是否集中在某一台。然后到这台机器上检查进程和端口、应用日志、线程池、GC,504 要沿调用链找慢的环节。最后检查配置:超时是否合理,上游长连接的空闲超时要短于应用服务器的空闲超时,避免 Nginx 使用已被对端关闭的连接。