Nginx 与负载均衡
Nginx 提供反向代理、HTTP 路由和负载均衡。本文负责连接模型、代理参数、LVS 模式与错误诊断。
1. 面试核心
先记住这几条,再读正文- 事件驱动。 Nginx worker 用事件循环处理连接,Linux 下可使用 epoll。卡 · Nginx 的结构与常用配置
- 负载均衡层次。 四层按连接分发,七层可按 HTTP 域名、路径和头部路由。卡 · 负载均衡
- 连接缓存。
keepalive指定每个 worker 的上游空闲连接缓存。卡 · 连接容量 - 读取超时。
proxy_read_timeout限制相邻两次读取间的等待时间。卡 · 代理超时与重试 - 网关错误。 502 指向上游通信异常,504 指向网关等待上游超时。卡 · 502 与 504
2. Nginx 的结构与常用配置
master 读取配置并管理 worker。worker 通过事件循环处理已就绪的网络操作。worker_processes auto 根据可用 CPU 自动设置数量。
非阻塞网络 I/O 能让少量 worker 管理大量连接。磁盘访问、复杂计算或阻塞模块仍会拖慢事件循环。文件 I/O 可按平台和配置使用异步机制或线程池。
Apache 的 prefork、worker 与 event MPM 有不同模型。比较性能应说明使用的 MPM、模块与工作负载。
下面片段放在 http 上下文中。
upstream backend {
least_conn;
server 10.0.0.11:8080 weight=2 max_fails=3 fail_timeout=10s;
server 10.0.0.12:8080 max_fails=3 fail_timeout=10s;
keepalive 64;
}
server {
listen 8080;
server_name example.com;
location /static/ {
root /data/www;
expires 7d;
}
location /api/ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 3s;
proxy_read_timeout 30s;
}
}
/static/a.css 映射到 /data/www/static/a.css。上游接收到的请求仍带 /api/ 前缀。HTTP/1.1 与清空 Connection 配合上游连接复用。
Nginx 1.29.7 前默认代理 HTTP/1.0。1.29.7 起默认是 HTTP/1.1。显式配置便于跨版本说明意图。
nginx -t 检查配置语法及引用文件。通过后可用 nginx -s reload 重载。master 成功应用新配置后,启动新 worker。旧 worker 完成已有请求后退出。
2.1 连接容量
worker_connections 约束每个 worker 的连接数。客户端和上游连接都占用额度。HTTP 反向代理的一次活跃请求可占两侧连接。
文件描述符上限也约束实际容量。因此,worker 数量乘连接额度只给出粗略上界。HTTP/2 多路复用和上游复用还会改变比例。
keepalive 64 表示每个 worker 缓存最多 64 条空闲连接。活跃上游连接可超出该值。上游并发控制需另行配置和评估。
3. 负载均衡
| 算法 | 配置 | 适用条件 |
|---|---|---|
| 加权轮询 | weight | 按后端能力分配请求 |
| 最少连接 | least_conn | 请求占用时间差异较大 |
| IP 哈希 | ip_hash | 需要按地址粘滞,注意 NAT 聚集 |
| 一致性哈希 | hash $request_uri consistent | 缓存按键分布 |
被动健康检查记录上游失败。max_fails=3 fail_timeout=10s 表示窗口内达到三次失败。后端随后在指定时段内被视为不可用。失败类型受 proxy_next_upstream 等配置影响。只有一个后端时,max_fails 与 fail_timeout 会被忽略。
四层关注连接与地址端口,七层解析应用协议。Nginx stream 也能提供四层代理。四层全代理会拆成两条连接,LVS NAT、DR 则转发原连接。具体性能需结合实现、TLS 和请求负载测试。
| LVS 模式 | 请求与响应路径 |
|---|---|
| NAT | 改写目的地址;响应也经调度器反向转换 |
| DR | 修改目的 MAC;后端直接响应客户端 |
| TUN | 封装转发;后端解封装后直接响应 |
DR 要求调度器和后端处于可直达的二层网络。后端配置 VIP,并约束 VIP 的 ARP 应答。TUN 依赖隧道和底层可达性。绕过响应流量可减轻调度器带宽压力。
FULLNAT 属于特定 LVS 扩展实现,例如阿里 LVS。它同时改写源、目的地址。TOA 等扩展可传递客户端地址,需两端配合。部署时需确认实现支持。
Keepalived 可用 VRRP 协调 VIP 主备切换。健康检查还可维护 LVS 后端列表。接管 VIP 后,业务恢复仍依赖容量和连接状态。
4. 502 与 504
| 状态 | 解释与线索 |
|---|---|
| 500 | 当前响应方内部错误,可由应用或代理产生 |
| 502 | 上游连接失败、无有效响应或无可用后端 |
| 503 | 服务不可用;Nginx limit_req 默认拒绝码 |
| 504 | 网关等待上游超时 |
| 499 | Nginx 日志记录客户端提前关闭 |
上游返回的状态码也可被代理直接传递。应结合 upstream_status、错误日志与应用日志定位。无可用上游的 no live upstreams 对应 502。
- 查看 error.log,确认连接、响应头或读取阶段。
- 对比 upstream_addr、upstream_status 与各阶段耗时。
- 核对异常后端的监听、负载、线程池和依赖。
- 检查超时、连接复用及重试配置。
- 用用户请求成功率与延迟验证修复。
Connection refused 表示连接遭到明确拒绝。进程未监听是原因之一,策略拒绝也需核对。upstream timed out 则需结合日志中的阶段定位。
5. 代理超时与重试
proxy_connect_timeout 控制上游建连等待。proxy_send_timeout 控制相邻写操作间的等待。proxy_read_timeout 控制相邻读操作间的等待。持续返回数据的响应可超过该读取超时值。
proxy_next_upstream 配置失败后换后端的条件。proxy_next_upstream_tries 限制重试次数。proxy_next_upstream_timeout 限制总重试窗口。响应已发给客户端后,换后端无法重新完成该响应。
已发给上游的 POST 等非幂等请求,默认不会这样重试。non_idempotent 会放宽该限制。业务重试仍需幂等键,因为超时后原请求也可能已提交。
6. 路径映射与真实地址
在普通前缀 location 中,proxy_pass 的 URI 决定替换方式。
location /api/ {
proxy_pass http://backend/;
}
请求 /api/users 会转为上游 /users。去掉 backend 后面的斜杠,则保留 /api/users。正则 location 和带变量配置有额外规则。
root 将 URI 拼到根目录后。alias 将匹配的位置替换为指定路径。静态文件排查应根据最终映射检查路径权限。
X-Forwarded-For 可携带代理链地址,客户端也能伪造该头。real_ip 模块需用 set_real_ip_from 指定可信代理。源地址用于限流或审计前,必须明确可信入口。
7. 请求限流
limit_req_zone $binary_remote_addr zone=perip:10m rate=10r/s;
server {
listen 8081;
location / {
limit_req zone=perip burst=20 nodelay;
limit_req_status 429;
proxy_pass http://backend;
}
}
此片段也放在 http 上下文中。limit_req 按泄漏桶方法控制请求速率。burst 提供超额请求额度。nodelay 允许额度内的突发立即处理。超过额度时拒绝,示例返回 429。
limit_conn 约束并发连接,与请求速率是不同维度。按 IP 限流还需考虑 NAT 用户共享地址。
8 · 面试题卡片
本页题目与参考回答
8.1 Nginx 有什么作用?它为什么能支撑很高的并发?与 Apache 有什么区别?
考察重点
- master/worker 进程模型与 epoll 事件驱动。
- 常用功能与动静分离;与 Apache 连接模型的差异。
相关内容:Nginx 的结构与常用配置、I/O 多路复用。
参考回答
Nginx 用事件循环和非阻塞网络 I/O 管理大量连接。
master 管理 worker,worker 处理就绪事件。Linux 可使用 epoll。阻塞模块和重计算仍会影响同一 worker 的请求。
它可做反向代理、静态服务、TLS、缓存与限流。配置重载时启动新 worker,旧 worker 逐步退出。容量还受连接数、文件描述符和上游能力约束。
Apache 各 MPM 的连接处理模型不同。比较时应明确 prefork、worker 或 event。工作负载与模块配置比产品名称更能解释差异。
8.2 四层负载均衡和七层负载均衡有什么区别?Nginx 和 LVS 怎样选择?LVS 有哪几种模式?
考察重点
- 四层与七层的依据、能力和性能差异;Nginx 的负载均衡算法。
- LVS 各模式的报文路径与限制;Keepalived 的 VRRP。
参考回答
四层按连接分发,七层可按应用内容路由。
LVS 在内核中转发,Nginx HTTP 代理解析请求。Nginx stream 也能承担四层代理。
LVS NAT 的响应经过调度器。DR 改目的 MAC,后端直接响应。TUN 封装请求,后端解封装并直接响应。FULLNAT 是特定扩展,实现需单独确认。
Nginx 支持加权轮询、最少连接和哈希。Keepalived 用 VRRP 协调 VIP,并可检查后端。选择方案时应考虑路由能力、容量与运维复杂度。
8.3 Nginx 返回 502 和 504 分别是什么原因?怎样排查?和 500 有什么区别?
考察重点
- 状态码由谁产生;502 与 504 的典型原因。
- 从 Nginx 错误日志和上游字段定位到具体后端;长连接复用导致的 502。
相关内容:502 与 504、Linux 网络排查。
参考回答
502 表示上游通信异常,504 表示网关等待上游超时。
500 表示响应方内部错误,应用和代理都可产生。状态码也可能由上游透传。
先看 error.log 的错误阶段。再结合 upstream_addr、upstream_status 和耗时定位后端。检查监听、负载、池等待及依赖。复用连接被对端关闭时,应核对双方空闲超时。
proxy_read_timeout 限制相邻读取的等待。超时处理需结合业务期限和重试副作用。无可用上游会产生 502,应检查被动健康状态。
8.4 worker_connections 与 keepalive 能直接算出业务并发上限吗?
考察重点:双侧连接、文件描述符与空闲缓存。
相关内容:连接容量。
参考回答
worker_connections 包含客户端和上游连接。
实际容量还受文件描述符及业务处理能力约束。keepalive 只限制每个 worker 的上游空闲缓存。活跃连接可超过该数量,需独立评估上游并发。
8.5 proxy_read_timeout=30s 会限制总响应时间吗?POST 超时能否换后端重试?
考察重点:相邻读超时、重试窗口与幂等性。
相关内容:代理超时与重试。
参考回答
它限制相邻两次读取间的等待。
持续返回数据时,总响应可超过 30 秒。已发送的非幂等请求默认不会换后端重试。non_idempotent 可放宽限制,但需业务幂等保护。次数和时间窗口也应通过重试参数限制。
8.6 proxy_pass 末尾斜杠有什么影响?怎样可信地取得客户端地址?
考察重点:URI 替换规则与可信代理。
相关内容:路径映射与真实地址。
参考回答
普通前缀 location 中,proxy_pass 是否带 URI 决定是否替换匹配前缀;客户端地址则只能从可信代理提供的信息中取得。
例如 location /api/ 配合 proxy_pass http://backend/ 时,/api/users 转为 /users;改成不带 URI 的 proxy_pass http://backend 时保留原路径。
客户端可伪造 X-Forwarded-For。配置 real_ip 时,只信任 set_real_ip_from 指定的代理。
8.7 limit_req 的 burst 与 nodelay 分别做什么?
考察重点:平均速率、突发额度与拒绝行为。
相关内容:请求限流。
参考回答
burst 允许一定数量的超额请求。
默认会按配置速率延迟处理。nodelay 让额度内突发立即通过。超过额度仍会拒绝。limit_req_status 可将拒绝码设为 429。并发连接上限由 limit_conn 等机制另行控制。
9. 参考资料
- nginx documentation:Using nginx as HTTP load balancer
- nginx documentation:ngx_http_upstream_module
- Linux Virtual Server:LVS 文档
- Keepalived 文档
- nginx:Core functionality
- nginx:HTTP proxy module
- nginx:HTTP core module
- nginx:Real IP module
- nginx:Request limiting
- nginx:Controlling nginx
- Alibaba LVS:FULLNAT