谈谈 HTTP 的缓存机制,服务器如何判断缓存是否过期?

HTTP缓存机制与缓存过期判断

一、HTTP缓存概述

HTTP缓存是一种性能优化机制,通过在客户端或中间代理存储资源的副本,减少对服务器的请求,从而加快页面加载速度,降低服务器负载。

二、缓存位置

  1. 私有缓存(浏览器缓存):单个用户专用
  2. 共享缓存(代理缓存/CDN):多个用户共享

三、HTTP缓存控制头

1. 缓存控制头(Cache-Control)

这是HTTP/1.1中控制缓存的主要机制,常用指令:

http 复制代码
Cache-Control: max-age=3600, public, must-revalidate

关键指令:

  • max-age:资源被认为新鲜的最大时间(秒)
  • s-maxage:共享缓存(如CDN)的最大新鲜时间
  • public:响应可以被任何缓存存储
  • private:响应只能被私有缓存存储
  • no-cache:每次使用前必须向服务器验证
  • no-store:禁止任何缓存
  • must-revalidate:过期后必须向服务器验证
  • immutable:资源永不变,适合版本化资源

2. 过期头(Expires)

HTTP/1.0的缓存机制,指定绝对过期时间:

http 复制代码
Expires: Wed, 21 Oct 2023 07:28:00 GMT

四、服务器判断缓存是否过期的机制

1. 基于时间的过期判断(强制缓存)

服务器设置资源的新鲜期(freshness lifetime),浏览器在此期限内直接使用缓存:

javascript 复制代码
// 新鲜期计算逻辑
function isCacheFresh(response) {
    // 优先使用 Cache-Control 的 max-age
    if (response.headers['Cache-Control']?.includes('max-age=')) {
        const maxAge = parseInt(response.headers['Cache-Control'].match(/max-age=(\d+)/)[1]);
        const age = getCurrentAge(response); // 计算当前缓存年龄
        return age < maxAge;
    }
    
    // 其次使用 Expires
    if (response.headers['Expires']) {
        const expiresDate = new Date(response.headers['Expires']);
        const now = new Date();
        return now < expiresDate;
    }
    
    // 启发式过期(当没有明确指示时,浏览器自行估算)
    return false;
}

2. 验证机制(协商缓存)

当缓存过期或需要验证时,浏览器向服务器发送验证请求:

a) Last-Modified / If-Modified-Since
http 复制代码
# 第一次请求,服务器响应
HTTP/1.1 200 OK
Last-Modified: Wed, 21 Oct 2023 07:28:00 GMT
Cache-Control: max-age=3600

# 缓存过期后,浏览器发送验证请求
GET /resource.jpg HTTP/1.1
If-Modified-Since: Wed, 21 Oct 2023 07:28:00 GMT

# 服务器响应(未修改)
HTTP/1.1 304 Not Modified
# 不返回内容体,浏览器使用缓存
b) ETag / If-None-Match(更精确)
http 复制代码
# 第一次请求
HTTP/1.1 200 OK
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
Cache-Control: max-age=3600

# 缓存过期后
GET /resource.jpg HTTP/1.1
If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"

# 资源未改变
HTTP/1.1 304 Not Modified

五、缓存验证流程

graph TD A[浏览器发起请求] --> B{检查本地缓存} B -->|无缓存| C[向服务器请求] B -->|有缓存| D{检查新鲜度<br>(未过期)} D -->|新鲜| E[直接使用缓存<br>(不请求服务器)] D -->|不新鲜| F[准备验证请求] F --> G{服务器有设置ETag?} G -->|是| H[添加 If-None-Match 头] G -->|否| I{服务器有设置 Last-Modified?} I -->|是| J[添加 If-Modified-Since 头] I -->|否| C H --> K[发送验证请求] J --> K K --> L{服务器验证} L -->|未修改| M[返回 304 Not Modified<br>浏览器使用缓存] L -->|已修改| N[返回 200 + 新内容<br>更新缓存] C --> O[返回 200 + 新内容] O --> P[存储到缓存]

总结

服务器判断缓存是否过期主要依赖两个机制:

  1. 时间基准 :通过Cache-Control: max-ageExpires设置新鲜期
  2. 验证基准 :通过ETag/If-None-MatchLast-Modified/If-Modified-Since验证内容是否变更

合理配置缓存策略可以显著提升网站性能,减少服务器负载,改善用户体验。

相关推荐
XiYang-DING20 分钟前
地图城市缓存优化:ApplicationReadyEvent + Caffeine + Redis + Redisson 分布式锁
redis·分布式·缓存
暧暧内含光1 小时前
一文讲透浏览器缓存四种方式(没有废话版)
http
Titan20241 小时前
HTTPS基础知识梳理
服务器·网络·c++·网络协议·学习·http·https
智脑API1 小时前
CCSwitch Claude Code 如何配置 MCP?服务器启动、工具权限与安全测试
运维·服务器·claude·codex·ccswitch
DolitD2 小时前
云流技术深度剖析:单服务器下如何实现3D应用的多实例并发?
java·服务器·前端·3d·云原生·云计算
jun_bai2 小时前
Ecplise中发布项目到配置的tomcat中
java·服务器
芦柑4642 小时前
画布和3D导演台工具:短剧分镜从素材整理到空间预演的完整链路
服务器·前端·数据库
闲云野鹤在人间2 小时前
KVM虚拟化实战|CentOS‑Stream8 两种安装方式+模板制作+基础使用
linux·运维·服务器·centos
小张同学a.2 小时前
Docker 容器实战 2—— docker 仓库
linux·运维·服务器·docker·容器
Android系统攻城狮2 小时前
Linux PipeWire深度解析之pw_core_get_registry调用流程与实战(九十一)
linux·运维·服务器·音频进阶·pipewire音频实战进阶