要让 proxy_cache_lock 在数万 HTTPS 并发下真正拦住回源击穿,关键不是“开了锁”,而是确保缓存存在、key 一致、timeout 合理、stale 有退路:必须定义 keys_zone、启用 proxy_cache、统一 proxy_cache_key(如 "$scheme$host$request_uri")、设 proxy_cache_lock_timeout 6–10s 并配 proxy_cache_use_stale error timeout updating,再通过 $upstream_cache_status 和压测验证 MISS→LOCKING→HIT 行为。

要让 proxy_cache_lock 在数万 HTTPS 并发连接下真正拦住回源击穿,关键不是“开了锁”,而是确保每个环节都对齐:缓存必须存在、key 必须一致、锁必须能等到结果、失败时有退路。HTTPS 本身不改变机制,但 TLS 握手开销和 header 差异更容易干扰缓存命中,需针对性处理。
必须先建好缓存基础,否则 lock 形同虚设
proxy_cache_lock 只在 cache miss 时起作用,而 miss 的前提是 Nginx 真正在用缓存。缺一不可:
- 在
http块定义共享内存缓存区:proxy_cache_path /var/cache/nginx/proxy_cache levels=1:2 keys_zone=my_cache:20m max_size=2g inactive=60m use_temp_path=off;
——keys_zone=my_cache:20m是核心,20MB 内存可支撑约 16 万个 key,适合万级并发场景 - 在对应
location中启用缓存:proxy_cache my_cache;<br>proxy_cache_valid 200 302 10m;<br>proxy_cache_valid 404 1m;
- 确认没被绕过:检查是否误配了
proxy_no_cache、proxy_cache_bypass,或响应头含Cache-Control: no-cache、Set-Cookie(后者需显式忽略)
统一缓存 key,堵死 HTTPS 带来的干扰源头
HTTPS 请求常携带动态 header(如 Authorization、User-Agent、Cookie)或随机 query(如 ?t=1623456789),导致同一资源生成多个 key,锁就完全失效。
- 强制简化 key,剥离无关字段:
proxy_cache_key "$scheme$host$request_uri";
——忽略$args、$cookie_*、$http_*等所有可能变动的部分 - 若接口依赖域名或路径前缀做路由,可进一步收束:
proxy_cache_key "$host:/api/v1/product/detail";
——把所有商品详情请求锁定到同一个 key - 禁用后端干扰缓存的响应头:
proxy_ignore_headers Set-Cookie Vary Cache-Control Expires;
——避免因Set-Cookie或Vary: User-Agent导致响应被跳过缓存
调优 lock_timeout 与 stale 策略,应对真实高负载
数万连接涌入时,首个回源请求可能因后端排队、DB 锁争抢而变慢。timeout 设太短,等待队列会集体超时并发回源;设太长,大量连接卡在 wait 状态,耗尽 worker 连接。
- 根据后端 P95 响应时间设
proxy_cache_lock_timeout:
若后端通常 3–5 秒返回,设为6s;若偶发毛刺达 8 秒,可设10s,但不宜超过 - 必须搭配
proxy_cache_use_stale提供兜底:proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
——当首个请求失败或超时,等待中的请求可直接用旧缓存,而非全部转为回源 - 开启后台更新,减少用户感知延迟:
proxy_cache_background_update on;
——缓存过期后,首个请求触发回源并更新,其余请求继续读旧内容,无等待
验证是否真生效,别只看配置写了没
光配对不等于起效。需通过日志和压测交叉验证:
- 在 log_format 中加入
$upstream_cache_status:log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for" $upstream_cache_status'; - 压测时模拟 1000+ 并发访问同一未缓存 URL,观察 access log:
应看到少量MISS(首个请求)、大量LOCKING(等待中)、随后快速转为HIT;上游服务 QPS 应稳定在个位数,而非随并发线性飙升 - 检查 SSL 相关 header 是否意外进入 key:
用curl -I -k https://your.site/api/data --header "Cookie: session=abc123" --header "User-Agent: test/1.0",再对比无 header 的请求,确认两者X-Cache-Status一致











