Nginx 配置实战

共 20 题
📑 题目列表 20 题
#
★★★

1. Nginx location 匹配规则的优先级(精确/前缀/正则)与常见配置错误案例?

Nginx location 匹配规则(精确/前缀/正则)的优先级是什么?常见配置错误?

  • 精确匹配 = 优先,其次 ^~ 前缀,然后正则,最后普通前缀
  • 正则按顺序匹配,首个命中生效
  • 最长前缀匹配

Nginx location 匹配优先级:① 精确匹配 location = /path 最高;② 前缀匹配 ^~location ^~ /img)命中后不再查正则;③ 正则匹配 ~/~*(按配置顺序,首个命中生效);④ 普通前缀匹配(location /path),取最长前缀。规则:先精确,再 ^~,再正则(顺序),最后普通前缀最长。常见配置错误:正则放在普通前缀之后但被前缀抢先匹配(未用 ^~)、正则顺序错误导致命中错误 location、多个前缀重叠导致最长匹配不确定。用 location 的匹配语义需注意 = 精确、^~ 阻断正则、~ 正则。

优先级口诀是"精确 > ^~ > 正则 > 最长前缀"。正则按顺序首个命中,^~ 阻断正则,是最易出错的点。

location = /exact { ... }        # 精确
location ^~ /static/ { ... }     # 前缀,优先于正则
location ~ \.php$ { ... }        # 正则
location / { ... }                # 普通前缀兜底
#
★★★

2. Nginx 反向代理的关键配置中 proxy_pass 结尾斜杠差异、Host 头透传与超时三件套(connect/send/read)?

Nginx 反向代理的 proxy_pass 结尾斜杠差异、Host 头透传与超时三件套如何配置?

  • proxy_pass 结尾斜杠决定 URI 替换方式
  • proxy_set_header Host 透传 Host
  • 超时三件套:connect/send/read

proxy_pass 结尾斜杠差异:proxy_pass http://backend;(无 URI)会把完整请求 URI 传给上游;proxy_pass http://backend/;(带 URI)会用 / 替换 location 匹配的部分,即"location 前缀被替换为 proxy_pass 的 URI"。Host 头透传:proxy_set_header Host $host; 把客户端 Host 传给上游(或 $http_host),保证上游虚拟主机正确。超时三件套:proxy_connect_timeout(建连)、proxy_send_timeout(发送)、proxy_read_timeout(读取响应)。合理组合避免上游慢时客户端超时与误报。反代还要透传 X-Real-IP/X-Forwarded-For

proxy_pass 斜杠决定 URI 替换,Host 头决定虚拟主机,超时三件套控制代理各阶段。这是反代核心三要素。

location /api/ {
    proxy_pass http://backend/;   # 替换 /api/ 为 /
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_connect_timeout 5s;
    proxy_send_timeout 30s;
    proxy_read_timeout 30s;
}
#
★★★

3. Nginx 反向代理的核心配置中 upstream、proxy_pass、proxy_set_header 与 keepalive 如何协同?

Nginx 反向代理的 upstream、proxy_pass、proxy_set_header 与 keepalive 如何协同?

  • upstream 定义后端组与负载均衡/健康检查
  • proxy_pass 引用 upstream
  • proxy_set_header 透传请求头

Nginx 反代中:upstream 定义一组后端服务器(可配 weight、max_fails、keepalive),proxy_pass http://backend; 引用该 upstream 做负载均衡。proxy_set_header 透传/改写请求头(Host、X-Forwarded-For 等)。keepalive(upstream 内的 keepalive N)复用与上游建立的连接,减少 TCP 建连与 TLS 握手开销,提升性能。协同:upstream 管后端与连接复用,proxy_pass 管转发,proxy_set_header 管请求头,keepalive 管连接池。三者配合实现高效反代。

核心协同是"upstream 定义后端 + proxy_pass 转发 + proxy_set_header 传头 + keepalive 连接复用"。keepalive 显著降低建连开销。

upstream backend {
    server 10.0.0.1:80 weight=2;
    server 10.0.0.2:80;
    keepalive 32;
}
server {
    location / {
        proxy_pass http://backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header Host $host;
    }
}
#
★★★

4. try_files 与命名 location(@)在 SPA 路由回退与伪静态中的典型配置,以及内部跳转与外部跳转的区别

try_files 与命名 location(@)在 SPA 路由回退与伪静态中如何配置?内部与外部跳转区别?

  • try_files 按顺序检查文件,找不到走 fallback
  • 命名 location(@)做内部跳转
  • SPA 路由回退:try_files 到 index.html

try_files $uri $uri/ /index.html; 让 SPA 对不存在的路径回退到 index.html(前端路由接管)。命名 location @fallbacktry_files $uri @fallback; 做内部跳转,location @fallback { ... } 定义处理。内部跳转(内部重定向)不改变 URL、不产生新的 HTTP 请求,由 Nginx 内部调度(如 @X-Accel-Redirect);外部跳转(return/rewrite ... redirect)返回 301/302 让客户端重新请求。伪静态常配合 try_files 与 rewrite 实现。区别:内部跳转透明、外部跳转客户端可见并改变 URL。

try_files 是"文件优先 + 回退",@ 命名 location 做内部跳转。SPA 回退到 index.html,内部 vs 外部跳转决定是否客户端可见。

location / {
    try_files $uri $uri/ /index.html;
}
location @fallback {
    proxy_pass http://backend;
}
#
★★★

5. Nginx server_name 的精确/通配/正则匹配顺序与 default_server 兜底逻辑,无匹配请求如何安全处理

Nginx server_name 的匹配顺序与 default_server 兜底逻辑?无匹配请求如何处理?

  • server_name 精确 > 通配(*)> 正则匹配顺序
  • 无匹配时用 default_server(listen 上的 default_server)
  • 未配置 default_server 时用第一个 server

Nginx 选择 server 的顺序:精确匹配 server_name > 以 * 开头的通配 > 以 * 结尾的通配 > 正则(按配置顺序首个命中)。若无匹配,选 listen 上的 default_server 兜底;若未声明 default_server,用该端口的第一个 server。无匹配请求(如访问未知 Host)应安全处理:默认返回该 server 的默认响应,可配置 default_server 返回 444(关闭连接)或 403,避免泄露或误处理。listen 80 default_server; 声明兜底 server。安全上不让未知 Host 落到业务 server。

匹配顺序是"精确 > 通配 > 正则",default_server 兜底无匹配。安全上未知 Host 应返回 444/403 而非默认业务。

server {
    listen 80 default_server;
    server_name _;
    return 444;   # 关闭连接
}
#
★★

6. Nginx rewrite 与 return 的区别及 301/302/307 跳转的选择?

Nginx rewrite 与 return 的区别?301/302/307 跳转如何选择?

  • rewrite 改写 URI 再继续处理,return 直接返回
  • 301 永久、302 临时、307 保留方法
  • 场景选择:SEO/永久迁移用 301,临时用 302,POST 保留用 307

Nginx 的 rewrite 改写 URI 后继续处理(可多次、可配合 location),return 直接返回状态码与响应,不再处理。rewrite 适合 URI 重写,return 适合跳转/拦截。跳转选择:301 永久重定向(SEO 合并、域名迁移),302 临时重定向(临时切换),307 临时重定向但保留请求方法(POST 不转 GET)。黄金规则:永久迁移用 301,临时用 302,POST 表单需保留方法用 307,308 为永久保留方法。性能上 return 直接返回比 rewrite 高效。rewrite ... redirectrewrite ... permanent 也产生 302/301。

rewrite 是"改写继续",return 是"直接返回"。301/302/307 按"永久/临时/保留方法"选择。

return 301 https://new.example.com$request_uri;
rewrite ^/old/(.*)$ /new/$1 permanent;
return 307 /new;   # 保留 POST 方法
#
★★

7. Nginx upstream 主动健康检查(商业版/第三方)与被动健康检查(max_fails/fail_timeout)的区别与选择

Nginx upstream 主动 vs 被动健康检查的区别与选择?

  • 被动:max_fails/fail_timeout 按请求失败标记
  • 主动:商业版/第三方定期探测
  • 区别:被动看请求、主动看探针

Nginx 默认是被动健康检查:max_fails(失败次数)与 fail_timeout(窗口)——在某时间窗口内请求失败达到次数则标记该后端不可用,转发到其他后端。它不需要额外探测,但只在有请求时才感知故障。主动健康检查(Nginx 商业版 health_check 指令或第三方模块 nginx_upstream_check_module)定期向后端发探测请求(如 HTTP GET /health),主动发现故障,实时性好,但需额外模块/商业授权。选择:开源默认用被动(成本低),对实时性要求高或商业版可用主动。被动对高健康检查频率场景感知慢。

被动是"按请求失败标记",主动是"定期探针"。主动实时性好但需商业版/第三方,被动零成本但感知滞后。

upstream backend {
    server 10.0.0.1:80 max_fails=3 fail_timeout=5s;
    server 10.0.0.2:80 max_fails=3 fail_timeout=5s;
}
#
★★

8. Nginx 负载均衡策略(轮询/权重/ip_hash/least_conn/url_hash)的适用场景与一致性哈希扩展?

Nginx 负载均衡策略(轮询/权重/ip_hash/least_conn/url_hash)的适用场景?

  • 轮询默认、权重、ip_hash、least_conn、url_hash
  • 各策略适用场景
  • 一致性哈希扩展(第三方/keyword)

Nginx upstream 负载均衡策略:默认轮询(round-robin)均匀分配;weight 按权重分配(能力大的比例高);ip_hash 按客户端 IP 哈希固定到后端(会话保持);least_conn 分配给当前连接最少者(长连接/负载不均);url_hash 按 URL 哈希(缓存一致性,需第三方模块)。一致性哈希扩展:用 hash 指令(hash $request_uri consistent;)实现一致性哈希,后端增删时 rehash 最小,适合缓存。选择:同质轮询、长连接 least_conn、IP 会话 ip_hash、缓存一致性 url_hash/一致哈希。

策略选择取决于"连接特性与一致性需求"。hash 指令可做一致性哈希,ip_hash 会话保持,least_conn 抗长连接。

upstream backend {
    least_conn;
    server 10.0.0.1:80;
    server 10.0.0.2:80;
}
# 一致性哈希
upstream cache {
    hash $request_uri consistent;
    server 10.0.0.1:80;
    server 10.0.0.2:80;
}
#
★★

9. Nginx 限流(limit_req/limit_conn)与安全头、TLS 终止的典型配置组合?

Nginx 限流(limit_req/limit_conn)与安全头、TLS 终止如何组合配置?

  • limit_req 按请求速率限流、limit_conn 按连接数限流
  • burst/nodelay 突发控制
  • 安全头(HSTS/CSP 等)与 TLS 终止

Nginx 限流:limit_req_zone $binary_remote_addr zone=req:10m rate=10r/s; 定义请求速率限制,limit_req zone=req burst=20 nodelay; 应用(burst 允许突发、nodelay 立即处理)。limit_conn_zone $binary_remote_addr zone=conn:10m; + limit_conn conn 20; 限制并发连接。安全头用 add_header 加 HSTS、CSP、X-Content-Type-Options 等。TLS 终止在 server 配置 ssl_certificate、ssl_protocols TLSv1.2 TLSv1.3ssl_ciphers。组合:限流防滥用、安全头加固、TLS 终止加密,前端 server 统一配置,后端可明文。三者组合是生产反代的标准配置。

组合是"限流防滥用 + 安全头加固 + TLS 终止加密"。limit_req 配 burst/nodelay,limit_conn 限并发,安全头与 TLS 在 server 层。

limit_req_zone $binary_remote_addr zone=req:10m rate=10r/s;
server {
    listen 443 ssl;
    ssl_certificate /etc/ssl/cert.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    add_header Strict-Transport-Security "max-age=31536000" always;
    location / {
        limit_req zone=req burst=20 nodelay;
        proxy_pass http://backend;
    }
}
#
★★

10. Nginx 高并发调优中 worker_processes/worker_connections/keepalive_timeout 与文件描述符的配比?

Nginx 高并发调优的 worker_processes/worker_connections/keepalive_timeout 与文件描述符如何配比?

  • worker_processes 通常 = CPU 核数
  • worker_connections 每 worker 连接数
  • worker_rlimit_nofile 文件描述符上限

Nginx 高并发调优:worker_processes auto;(或 = CPU 核数)让每个 worker 处理一核;worker_connections 设每 worker 最大连接数(如 4096/10240);worker_rlimit_nofile 设文件描述符上限(需 ≥ worker_connections 的几倍,因为每个连接占用 fd);keepalive_timeout 控制客户端连接保持时间(合理缩短释放 fd)。总并发上限 ≈ worker_processes × worker_connections,但受 fd 限制:worker_rlimit_nofile 至少为 worker_connections × 2(读+写 fd)。还需调 ulimit -n 与系统 fs.file-max。配比原则:worker 数=核数、fd 满足连接需求、keepalive 平衡 fd 与连接复用。

高并发核心是"worker 数 = 核数、fd 上限 ≥ 连接数、keepalive 平衡"。总连接受 worker_connections × worker 与 fd 双重约束。

worker_processes auto;
worker_rlimit_nofile 65535;
events {
    worker_connections 10240;
}
http {
    keepalive_timeout 65;
}
#
★★

11. map 指令实现按变量(UA/区域/参数)映射分发与条件标头的典型用法

Nginx 的 map 指令如何实现按变量映射分发与条件标头?

  • map 根据变量值映射到结果
  • 按 UA、区域、参数映射
  • 配合条件标头(add_header)

map 指令根据源变量值映射出目标值,常用作分发与条件。map $http_user_agent $backend { default web; ~*iPhone mobile; } 按 UA 映射到不同后端。map $remote_addr $is_cn { default 0; 202.0.0.0/8 1; } 按区域映射。map $arg_platform $cdn { default off; mobile on; } 按参数映射。映射结果可用于 proxy_passadd_header(条件标头)、if 条件。例如按 UA 发的 add_header X-Mobile $is_mobile。map 在 http 块定义,hash 高效,是条件化的分发/标头工具。

map 是"变量→值"的映射表,用于按 UA/区域/参数做分发与条件标头。它比 if 更高效、语义清晰。

map $http_user_agent $backend {
    default       web;
    ~*iPhone|Android  mobile;
}
server {
    location / {
        proxy_pass http://$backend;
    }
}
#
★★

12. WebSocket/SSE 长连接代理中 Upgrade/Connection 头透传、proxy_read_timeout 与 proxy_buffering off 如何配合避免断流

Nginx 代理 WebSocket/SSE 长连接如何配置避免断流?

  • Upgrade/Connection 头透传(HTTP/1.1)
  • proxy_read_timeout 调大防断流
  • proxy_buffering off 流式

Nginx 代理 WebSocket/SSE 长连接需:① 透传 UpgradeConnection: upgrade 头,并设置 proxy_http_version 1.1(WebSocket 需要 HTTP/1.1 无 keepalive 转换);② proxy_read_timeout 调大(如 60s/3600s),防止空闲超时被 Nginx 断开;③ proxy_buffering off 关闭缓冲,让 SSE/事件流实时推送不堆积。SSE 还要 add_header X-Accel-Buffering no。这些组合避免长连接因超时/缓冲而断流。WebSocket 用 location 指定,SSE 用 streaming 响应。

长连接核心是"Upgrade 头透传 + 大 read_timeout + 关缓冲"。WebSocket 需 HTTP/1.1 与 Upgrade,SSE 需流式不缓冲。

location /ws {
    proxy_pass http://backend;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 3600s;
}
location /events {
    proxy_pass http://backend;
    proxy_buffering off;
    add_header X-Accel-Buffering no;
}
#
★★

13. nginx -s reload 的平滑机制中 worker 优雅退出、配置生效过程与 reload 失败时的回退保护

nginx -s reload 的平滑机制是什么?reload 失败如何回退?

  • reload 重新加载配置,优雅结束旧 worker
  • 新 worker 用新配置,旧 worker 处理完旧连接
  • reload 失败时保留旧配置

nginx -s reload 触发平滑重载:主进程重新读取配置,若语法错误则保留旧配置并报错(不中断服务);若正确,启动新 worker 用新配置,同时旧 worker 优雅退出(处理完当前连接后退出)。整个过程不中断存量连接,实现平滑升级。reload 失败的保证:若配置有错,reload 失败但旧 worker 与旧配置继续运行,服务不中断(回退保护)。nginx -t 可先测试配置。优雅退出基于 worker_shutdown_timeout 限制等待。reload 不重置连接,是零停机的配置更新方式。

reload 的核心是"新 worker 接管 + 旧 worker 优雅退出 + 失败保留旧配置"。它实现零停机配置更新,配置错误不会中断服务。

nginx -t && nginx -s reload   # 先测试再重载
nginx -s reload
#

14. Nginx upstream 的权重与备份节点配置中 backup/down 状态在故障切换时的行为

Nginx upstream 的权重与 backup/down 节点在故障切换时的行为?

  • weight 控制负载比例
  • backup 备份节点,仅当主节点都不可用时接管
  • down 手动下线节点

Nginx upstream 支持 weight(负载权重)、backup(备份节点)、down(手动下线)。backup 节点只在所有主节点都不可用时才被启用,用于灾备兜底;down 节点被手动标记不可用,不接收请求(用于维护)。故障切换行为:主节点因健康检查失败被标记不可用后,请求转发到仍可用的主节点,若全部主节点不可用则启用 backup 节点。weight 控制各后端接收请求的比例。max_fails/fail_timeout 决定主节点何时被标记失败。backup/down 使运维能控制故障切换与维护。

weight 管负载、backup 兜底、down 下线。backup 只在主全挂时接管,down 用于主动维护。

upstream backend {
    server 10.0.0.1:80 weight=3;
    server 10.0.0.2:80 weight=1;
    server 10.0.0.3:80 backup;   # 备份
    server 10.0.0.4:80 down;     # 下线
}
#

15. Nginx 动静分离与缓存(proxy_cache/open_file_cache)的配置与失效策略?

Nginx 动静分离与缓存(proxy_cache/open_file_cache)如何配置与失效?

  • 动静分离:静态走 Nginx、动态走上游
  • proxy_cache 缓存上游响应
  • open_file_cache 缓存文件句柄

动静分离:静态资源(图片/CSS/JS)由 Nginx 直接提供或本地缓存,动态请求(API)代理到上游。proxy_cache 缓存上游响应:proxy_cache_path /cache keys_zone=static:10m; + proxy_cache static; + proxy_cache_valid 200 1h;,按 cache key 缓存,命中直接返回。失效策略:按 Cache-Control/proxy_cache_valid 设置 TTL,proxy_cache_purge 手动清理,配合 proxy_cache_key(含 host/URI)。open_file_cache 缓存文件描述符与元数据,提升静态文件性能:open_file_cache max=1000 inactive=20s;。两者结合:静态用 open_file_cache 加速,动态/上游用 proxy_cache 缓存。

动静分离是"静态本地、动态上游"。proxy_cache 缓存上游响应,open_file_cache 缓存文件句柄,失效用 TTL/手动清理。

proxy_cache_path /var/cache/nginx keys_zone=static:10m max_size=1g;
server {
    location ~* \.(jpg|css|js)$ {
        open_file_cache max=1000 inactive=20s;
        open_file_cache_valid 30s;
        proxy_cache static;
        proxy_cache_valid 200 1h;
        proxy_pass http://backend;
    }
}
#

16. Nginx 安全加固要点中隐藏版本号、限制敏感 location、防目录遍历与请求体大小限制如何配置

Nginx 安全加固要点(隐藏版本、限制 location、防目录遍历、请求体限制)如何配置?

  • server_tokens off 隐藏版本号
  • 限制敏感 location(如 /admin 等敏感路径)
  • 防目录遍历(autoindex off)

Nginx 安全加固:server_tokens off; 隐藏版本号;敏感 location 用 allow/deny 限制(如 location /admin { allow 10.0.0.0/8; deny all; });autoindex off; 关闭目录列表防目录遍历;client_max_body_size 1m; 限制请求体大小防超大上传;配合 return 444 处理未知请求、禁用不必要方法(limit_except GET POST)。安全头(HSTS、CSP、X-Content-Type-Options)也属加固。请求体限制防 DoS 与恶意上传。关闭自动索引、隐藏版本、限制敏感路径是基础加固。

加固要点是"隐藏指纹、限制访问、防遍历、限请求体"。server_tokens 隐藏版本,allow/deny 限敏感路径,autoindex off 防遍历。

server_tokens off;
location /admin {
    allow 10.0.0.0/8;
    deny all;
}
location / {
    autoindex off;
    client_max_body_size 1m;
}
#

17. Nginx 日志排障中 access log 的 $upstream_status/$request_time 字段与 error log 级别如何配合定位 5xx

Nginx 日志如何用 $upstream_status/$request_time 与 error log 定位 5xx?

  • $upstream_status 上游状态、$request_time 请求耗时
  • 区分 5xx 在上游还是 Nginx
  • error log 级别(error/warn)辅助

$upstream_status 记录上游返回的状态码,$request_time 记录总请求耗时。当页面返回 5xx 时,看 access log:若 $status 是 502/504 而 $upstream_status 也是 502/504,说明上游出错;若 $status 5xx 但 $upstream_status 为空/200,说明 Nginx 自身出错(如 499 客户端断开)。$request_time 高往往伴随上游慢。error log 用 error_log /var/log/nginx/error.log warn; 记录连接/上游错误,级别(error/warn)控制详细度。配合 $upstream_addr 定位到具体上游。定位 5xx 的核心是区分"Nginx 层 vs 上游层"。

定位 5xx 的关键是"$upstream_status vs $status"。$upstream_status 反映上游,$request_time 反映耗时,error log 补充细节。

log_format main '$remote_addr $status $upstream_status $upstream_addr $request_time';
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log warn;
#

18. Nginx 缓存与限流的叠加场景中 proxy_cache 命中率统计与 limit_req 的 burst/nodelay 突发控制如何配置

Nginx 缓存与限流叠加的配置(proxy_cache 命中率与 limit_req burst/nodelay)?

  • proxy_cache 缓存静态/上游响应,命中率统计
  • limit_req 限流,burst/nodelay 突发控制
  • 叠加场景:缓存降压 + 限流防滥用

缓存与限流叠加:先 proxy_cache 缓存可缓存响应(降低回源压力、提高命中率),再用 limit_req 限制请求速率防滥用。命中率统计:$upstream_cache_status 记录 HIT/MISS/EXPIRED,可用日志统计命中率。limit_req 的 burst 允许突发令牌数(临时放行超过 rate 的请求),nodelay 表示突发请求立即处理(不排队),否则排队限速。叠加配置:静态/cacheable 走 proxy_cache,动态走限流,命中率提升 + 滥用被限。$upstream_cache_status 用于监控命中率与排查缓存失效。

叠加是"缓存降回源 + 限流防滥用"。burst/nodelay 控制突发,$upstream_cache_status 统计命中率。

limit_req_zone $binary_remote_addr zone=req:10m rate=10r/s;
location / {
    proxy_cache static;
    proxy_cache_valid 200 1h;
    limit_req zone=req burst=20 nodelay;
    proxy_pass http://backend;
}
# 日志含 $upstream_cache_status
log_format main '$status $upstream_cache_status $request_time';
#

19. gzip/brotli 压缩与静态资源缓存头(expires/Cache-Control)的动静分离配置组合

gzip/brotli 压缩与静态资源缓存头如何组合配置?

  • gzip/brotli 压缩传输
  • expires/Cache-Control 设置静态资源缓存
  • 动静分离组合

gzip 用 gzip on; gzip_types text/css application/javascript; gzip_min_length 1024; 压缩文本类资源;brotli 用 brotli on; brotli_types ...;(需模块)。静态资源缓存头用 expires 30d;(自动设 Cache-Control: max-age=2592000)或显式 add_header Cache-Control "public, max-age=31536000, immutable"。组合:静态资源(CSS/JS/图片)压缩 + 长缓存(immutable 表示不可变可永久缓存),动态资源不缓存或短缓存。动静分离:静态走 Nginx 压缩+缓存,动态走上游。压缩减少传输体积,缓存减少请求,两者结合提升静态资源性能。

gzip/brotli 减传输、expires/Cache-Control 减请求。静态资源压缩+长缓存、动态不缓存是动静分离的缓存策略。

gzip on;
gzip_types text/css application/javascript application/json;
gzip_min_length 1024;
location ~* \.(css|js|png)$ {
    expires 30d;
    add_header Cache-Control "public, immutable";
}
#

20. proxy_next_upstream 的重试触发条件与陷阱中非幂等请求重试导致重复提交如何规避

proxy_next_upstream 的重试触发条件与陷阱?非幂等请求重试如何规避?

  • proxy_next_upstream 触发转发到下一上游的条件
  • 默认 error/timeout;可加 http_500 等
  • 陷阱:非幂等请求重试导致重复提交

proxy_next_upstream 控制当前上游失败时是否转发到下一个上游,触发条件默认 error timeout,可加 http_500 http_502 等。陷阱:若上游在返回响应前失败(如超时、连接断开),Nginx 可能重试到下一个上游,但请求可能已在上游执行(如写入数据库),导致"重复提交"(非幂等操作被执行两次)。规避:① 对非幂等请求(POST 写操作)不启用 proxy_next_upstream 的 error/timeout(或只对幂等请求启用);② 应用层做幂等设计(唯一请求 ID、去重);③ 用 proxy_intercept_errors 控制。重试只适合幂等/无副作用请求。

陷阱是"上游可能已执行但响应丢失,重试导致副作用重复"。规避是"非幂等不重试 + 应用幂等 + 唯一 ID"。

location /api {
    proxy_pass http://backend;
    proxy_next_upstream error timeout http_500;
    # 非幂等写接口可设为 off
    proxy_next_upstream off;   # 或按 location 区分
}