304状态码不能直接衡量缓存命中率,它仅反映协商缓存成功的服务端确认,需结合Apache日志中特定资源的304占比、Cache-Control头分析及Chrome DevTools的“from disk/memory cache”数据综合评估。

304状态码本身不能直接衡量缓存命中率,但它在服务端(如Apache)日志中出现的频率,可作为客户端缓存是否生效的重要间接指标——前提是理解其触发条件和统计边界。
304响应的本质是“协商缓存成功”
当客户端发起带 If-Modified-Since 或 If-None-Match 请求头的请求,且服务端验证后发现资源未变更,就会返回304而非200。这表示:客户端本地副本仍有效,无需重传内容体,属于服务端确认的缓存复用。
- 它不等于“浏览器直接从内存/磁盘读取”(即完全无网络请求),而是经历了一次轻量HTTP往返
- 它依赖客户端主动携带校验头,而校验头是否发送,又取决于客户端是否持有有效的 Last-Modified 或 ETag 响应头
- 若客户端没发校验头(例如首次访问、缓存被清空、或Cache-Control: no-cache被误设),即使资源未变,也会收到200响应
Apache日志中304占比 ≠ 整体缓存命中率
仅看Apache access log 中 304 的比例会严重低估真实缓存效果,因为:
- 完全跳过服务器的请求不会出现在Apache日志里:例如设置了 Cache-Control: max-age=3600 且未过期,浏览器直接读本地副本,无任何网络请求
- CDN或反向代理可能拦截并响应304:此时请求根本未到达Apache,日志里看不到304,但缓存已生效
- 部分304来自非静态资源(如动态接口加了ETag),这类场景下304反映的是业务逻辑层的缓存策略,而非静态资源缓存效率
更合理的缓存效果评估方式
若目标是评估静态资源(JS/CSS/图片等)的客户端缓存效率,建议组合以下维度:
-
Apache中304请求数 / 所有该资源的GET请求数:聚焦特定路径(如
/static/js/app.js),排除动态接口干扰 -
搭配200响应中的Cache-Control头分析:统计含
max-age=且值较大的200响应占比,反映强缓存覆盖能力 - 借助Chrome DevTools → Network → Size列:观察“from disk cache”或“from memory cache”条目,这是最贴近用户实际体验的缓存命中数据
-
服务端埋点补充:在关键资源响应中写入自定义Header(如
X-Cache: HIT-FROM-APACHE-304),便于聚合分析
Java应用侧需注意的协同点
如果你用Java(如Spring Boot)提供资源,且前端通过Apache代理,那么缓存行为是两端共同决定的:
- Java端需正确设置 ETag(如用
ShallowEtagHeaderFilter)或 Last-Modified,否则Apache无法生成校验依据 - Apache需启用
mod_headers和mod_expires,并配置ExpiresByType或Header set Cache-Control,确保响应头传递到客户端 - 避免Java端与Apache缓存策略冲突:例如Java返回
Cache-Control: no-store,Apache再怎么配也没用
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










