事情本身不复杂,线索都在日志里。促销前蜘蛛抓取量从每分钟 60 次涨到 2400 次,Nginx 缓存命中率只有 12%,PHP-FPM 活跃进程被打满,页面响应从 200ms 涨到 6 秒。

把日志和配置对完,能解释这个现象的基本就这几处。缓存键带了 Cookie,蜘蛛每次请求的 cookie 不同就各存一份。另一种情况是列表页输出 Vary: Cookie,命中率必然为 0。

不容易想到的是,限流只配在 PHP 层,请求已经进入脚本才被拦。

上来先看缓存命中率与状态分布

awk '{print $9}' access.log | sort | uniq -c | sort -nr | head -5

再往下对匿名请求忽略 cookie

proxy_cache_bypass $cookie_nocache; proxy_ignore_headers Set-Cookie; proxy_cache_key "$scheme$host$request_uri";

等前面都确认过,再在 Nginx 层按 UA 限速

limit_req_zone $binary_remote_addr zone=crawl:10m rate=20r/s;

中途换过一次思路,把范围缩到最小的那一层,反而快了。

中间停过一次,把已经改的东西回滚干净,再重新来一遍。

恢复的判定其实很直接。缓存命中率升到 85% 以上,PHP-FPM 活跃进程回落到 10 以内,页面响应回到 250ms,日志里 499 与 502 同时下降。

容易忽略的是,忽略 Set-Cookie 要确认页面里没有用户相关内容,否则会把某个人的登录态发给所有访客。这类问题最好一次改到位,反复小改反而容易把原因搅混。

作者 9823189