在Web服务器运行过程中,资源的缓存验证是一项基础却关键的能力。Apache作为主流的HTTP服务器,依靠HTTP协议中的Last-Modified响应头与客户端发起的条件请求,实现了高效的协商缓存。当浏览器首次获取一个静态文件时,Apache会在响应里带上该文件在服务器上的最后修改时间,这个时间就是Last-Modified头的值。它采用GMT格式的时间字符串表示,例如类似某年某月某日某时刻的形态,用来标识资源内容发生最后一次变更的时间点。

到了第二次访问,浏览器不会盲目重新下载,而是自动在请求头中加入If-Modified-Since字段,把之前收到的Last-Modified时间原样发回给Apache。Apache接到请求后,会对比这个时间和文件当前的修改时间。如果文件在此期间没有被改动,服务器就直接返回状态码304 Not Modified,并且响应体为空,仅保留必要的头信息。这种做法让网络传输体量大幅下降,因为原本几KB到几MB的文件内容都不必重复发送。
Last-Modified头的基本定义
Last-Modified是HTTP响应头中的一种实体头字段,由源服务器生成,用于指出对应资源被修改的最终时间。在Apache环境下,对于静态文件诸如HTML、CSS、JS、图片等,这个头通常由核心模块mod_core根据文件系统上的mtime自动填充,管理员一般无需手动干预。它的存在意义在于为资源提供一个粗糙但实用的版本标记,客户端可据此判断本地副本是否仍然有效。
需要注意的是,Last-Modified的精度只到秒级,这在早期文件系统上足够,但如果同一秒内发生多次修改,就可能产生误判。此外,动态内容如PHP输出的页面,若没有在脚本里显式发送Last-Modified头,Apache不会自动补上,此时浏览器便无法利用该机制做验证。因此理解它的来源和局限,是正确配置缓存的前提。
304响应的触发逻辑
304状态码全称是Not Modified,属于重定向类但特殊的地方在于它不携带消息体。Apache在收到带条件请求头(If-Modified-Since或If-None-Match)的请求时,先评估条件是否成立。以Last-Modified体系为例,若请求中的If-Modified-Since时间等于或晚于文件当前修改时间,说明客户端持有的副本是最新的,Apache便中断实体输出,仅回304及少量头。
这种响应对用户体验影响明显:页面刷新时,许多静态素材走304,加载时间从几百毫秒降到几十毫秒,尤其在移动网络下更省流量。服务器侧也减轻了CPU与IO压力。不过若Apache被配置为不发送Last-Modified,或者应用层框架每次都强制返回200并附带内容,协商缓存就失效了,运维人员应定期检查响应头确认机制在运行。
Apache中的相关配置指令
在Apache配置文件或.htaccess里,有几个点会影响Last-Modified与304。首先是FileETag指令,它决定除Last-Modified外是否用inode、size、mtime组合生成ETag,浏览器可优先用ETag做更精确验证,但Last-Modified依旧常发。其次是ExpiresActive等模块控制过期时间,若设置了较长Cache-Control,浏览器可能连条件请求都不发,直接本地用缓存。
另一个常见情况是开启了压缩模块mod_deflate后,某些旧版Apache对压缩响应可能漏发Last-Modified,需要确认模块加载顺序与头信息保留。还有当使用反向代理或后端应用托管时,务必让前端Apache透传或正确设置这些头,否则原本该304的请求会变成200满响应,抵消性能优化。
用命令观察实际交互
我们可以借助curl工具在命令行模拟浏览器行为。第一次请求某文件时,加参数-i查看头,会看到Last-Modified出现。记下这个时间,第二次请求时手动加上头If-Modified-Since并赋同样的值,若服务器返回304,说明协商缓存工作正常。
示例流程如下:先执行普通GET看头,再带条件请求验证。如果本该304却收到200且带内容,应检查文件是否被意外改动、配置是否屏蔽了头、或应用是否每次都刷新修改时间。通过这种排查,能定位多数缓存异常。
| 请求类型 | 关键请求头 | Apache可能响应 |
|---|---|---|
| 首次请求 | 无条件头 | 200并带Last-Modified |
| 二次请求 | If-Modified-Since | 304(未变)或200(已变) |
| 带ETag请求 | If-None-Match | 304或200 |
常见误区与正确做法
有人以为只要用了Apache就自动所有资源都走304,实际上动态接口、带查询字符串且未配置缓存的脚本常不发送Last-Modified。还有人为了强制更新,在开发阶段完全关掉缓存头,上线后忘记恢复,导致带宽浪费。正确做法是静态资源依靠默认机制,动态内容在逻辑稳定时也应尽可能输出合理的Last-Modified或ETag。
另外,CDN层可能改写头,需要确认边缘节点与源站Apache的协同。遇到缓存不生效,不要急于改代码,先用前文命令看原始响应,再逐层排查。把Last-Modified与304这套基础协议用扎实,网站性能往往能有不小的自然提升。
ApacheLast-Modified304响应修改时间:2026-08-10 11:33:35