LRU淘汰需构建可复现的缓存生命周期环境:配置小缓存区(max_size=50m, inactive=30s),用多URI轮询制造冷热分离,再压满触发淘汰,通过命中率、文件时间戳和manager日志三重验证。

直接测试 proxy_cache 容量满时的 LRU 淘汰行为,关键不是“触发一次淘汰”,而是构建可观察、可复现的缓存生命周期环境,让 max_size 和 inactive 协同作用的过程清晰可见。
准备一个受控的缓存测试环境
先确保缓存配置本身支持明确的淘汰信号:
- 在
http块中定义小而独立的缓存区,例如:proxy_cache_path /var/cache/nginx/test_cache levels=1:2 keys_zone=test:10m max_size=50m inactive=30s use_temp_path=off;
(50m容易填满,30s的inactive方便人工观测) - 对应
location启用该缓存,并设置简单 key 和短有效期:proxy_cache test;proxy_cache_key "$uri";proxy_cache_valid 200 10s; - 后端返回固定内容并带唯一标识(如时间戳或序号),便于区分缓存项;可用 Python Flask 或 even
return 200 "hit-$(date +%s)";模拟。
主动填充并制造“冷热分离”状态
LRU 淘汰依赖访问时间顺序,需人为构造访问节奏:
⚠️ 已弃用 — 该技能已拆分为两个独立技能,以提升模块化程度:**webchat-https-proxy**(HTTPS/WSS 反向代理)和 **webchat-voi...**
- 用脚本循环请求一组 URI(如
/a,/b,/c, ...,/z),每轮间隔 1 秒,共跑 10 轮 → 这些路径会陆续写入缓存,且最后访问的在链表尾部。 - 等全部写入完成后(约 2 分钟),停止访问所有路径 40 秒以上 → 此时最早写入的几项已超
inactive=30s,但尚未达max_size上限。 - 再用另一个脚本高频请求一个新路径(如
/x1,/x2, ...),快速写入大量小文件,直到du -sh /var/cache/nginx/test_cache显示接近 50MB → 此时max_size触发,manager 进程开始按 LRU 清理。
验证淘汰是否按 LRU 执行
不靠猜,看三个客观证据:
-
查缓存命中率变化:用
curl -I http://host/a多次请求最早访问的路径(如/a),若返回X-Cache: MISS或响应体时间戳刷新,说明它已被淘汰;而最近访问的路径(如/z)仍为HIT。 -
看目录文件时间戳:进入
/var/cache/nginx/test_cache,用find . -type f -printf '%T@ %p\n' | sort -n查看文件修改时间。淘汰后残留的文件应集中在最近写入的批次,旧文件批量消失。 -
监控 manager 日志:开启
error_log /var/log/nginx/cache.log notice;,在日志中搜索cache manager,会看到类似:cache manager process 12345 exited with code 0cache manager started
它每次启动都代表一次淘汰周期,配合inactive和max_size触发条件可交叉印证。
避免常见干扰项
很多“没淘汰”其实是配置或环境问题:
-
proxy_cache_min_uses设为 2 或更高?那第一次请求根本不会落盘,自然无淘汰对象 —— 测试时建议设为 1 或注释掉。 - 缓存路径所在分区磁盘已满?Nginx 会静默失败,不报错也不淘汰,
df -h必须留出 10% 以上余量。 - 没配
proxy_cache_use_stale updating?高并发下多个请求同时回源,可能覆盖刚写入的缓存,造成“看似没命中”的假象。

















