Apache需启用mod_headers模块并按资源类型分层设置Cache-Control:静态资源用public,max-age=31536000,immutable;HTML设no-cache,must-revalidate;API用no-store或private,no-cache;配合FilesMatch或expr精准作用域,禁用ETag提升CDN命中率。

Apache 通过 Header 指令可以精准控制 Cache-Control 响应头,但必须确保 mod_headers 已启用,且策略要按资源类型分层设计,不能“一刀切”。
确认并启用 mod_headers 模块
很多 Apache 默认安装(尤其是 CentOS/RHEL 或某些 Docker 镜像)并未启用该模块,直接写 Header set 会触发 500 错误,错误日志中显示 Invalid command 'Header'。
- 检查是否已加载:
apachectl -M | grep headers,有输出说明已启用 - Debian/Ubuntu 系统:运行
a2enmod headers && systemctl reload apache2 - RHEL/CentOS 系统:编辑
httpd.conf,取消注释LoadModule headers_module modules/mod_headers.so,再执行systemctl reload httpd
按资源类型设置 Cache-Control 值
不同资源的更新频率和语义差异大,缓存策略必须区分对待。混用 no-cache 和长 max-age 会导致行为冲突,失去强缓存意义。
Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
-
静态资源(JS/CSS/图片/字体等):用
public, max-age=31536000, immutable(1年 + 不可变标记)。浏览器看到immutable后,即使过期也不会发条件请求,直接复用缓存 -
HTML 页面:禁用强缓存,设为
no-cache, must-revalidate或max-age=60。避免用户刷新后仍看到旧版页面 -
带哈希版本号的文件(如
app.a1b2c3.js):可放心设max-age=31536000,URL 变化天然触发缓存失效,无需担心内容陈旧 -
API 接口或动态 JSON:建议
no-store或private, no-cache,防止敏感数据被中间代理缓存
用 FilesMatch 或表达式限定作用域
避免全局 Header set 影响所有响应(比如把 HTML 也套上 immutable),要用作用域控制指令精准命中目标资源。
- 推荐写法(放在
<VirtualHost>或站点配置中):
<FilesMatch "\.(css|js|jpg|jpeg|png|gif|ico|svg|woff2|ttf)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
<p><FilesMatch ".html?$">
Header set Cache-Control "no-cache, must-revalidate"
</FilesMatch></p><h1>或使用更灵活的表达式(Apache 2.4+)</h1><p>Header set Cache-Control "no-cache" "expr=%{CONTENT_TYPE} =~ m#text/html#i"</p>-
FilesMatch更直观,适合基于扩展名的简单分类 -
expr=表达式更可靠,能识别真实 MIME 类型(例如 PHP 输出的 HTML 不依赖 .php 后缀)
配合 Expires 和 ETag 策略协同优化
Cache-Control 是 HTTP/1.1 的首选机制,但与 Expires、ETag 并非互斥,而是互补关系。
- 启用
mod_expires可自动生成Expires头,对老旧客户端(如 IE8)有兼容价值;但现代浏览器以Cache-Control为准 - 静态资源建议关闭
ETag(用FileETag None),避免因服务器配置差异导致 ETag 不一致,干扰 CDN 缓存命中 - 若需后台静默更新缓存,可加
stale-while-revalidate=86400,让过期后 24 小时内仍可返回旧资源,同时异步校验新版本

















