Apache 缓存配置 #
缓存概述 #
缓存类型 #
text
┌─────────────────────────────────────────────────────────────┐
│ Apache 缓存类型 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 浏览器缓存 │
│ ├── 通过 HTTP 头控制 │
│ ├── Expires / Cache-Control │
│ ├── 减少重复请求 │
│ └── 客户端控制 │
│ │
│ 服务器缓存 │
│ ├── mod_cache 模块 │
│ ├── 缓存后端响应 │
│ ├── 减少后端压力 │
│ └── 服务器控制 │
│ │
│ 代理缓存 │
│ ├── 反向代理缓存 │
│ ├── 缓存代理内容 │
│ └── CDN 缓存 │
│ │
└─────────────────────────────────────────────────────────────┘
浏览器缓存配置 #
启用必要模块 #
bash
# Ubuntu/Debian
sudo a2enmod expires
sudo a2enmod headers
sudo systemctl restart apache2
mod_expires 配置 #
apache
# ============================================
# mod_expires 浏览器缓存配置
# ============================================
<IfModule mod_expires.c>
# 启用过期控制
ExpiresActive On
# 默认缓存时间
ExpiresDefault "access plus 1 month"
# HTML 文件 - 短缓存
ExpiresByType text/html "access plus 1 hour"
# CSS 和 JavaScript - 长缓存
ExpiresByType text/css "access plus 1 year"
ExpiresByType text/javascript "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType application/x-javascript "access plus 1 year"
# 图片文件 - 长缓存
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType image/x-icon "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
# 字体文件 - 长缓存
ExpiresByType font/woff "access plus 1 year"
ExpiresByType font/woff2 "access plus 1 year"
ExpiresByType application/font-woff "access plus 1 year"
ExpiresByType application/font-woff2 "access plus 1 year"
ExpiresByType application/vnd.ms-fontobject "access plus 1 year"
ExpiresByType font/ttf "access plus 1 year"
ExpiresByType font/otf "access plus 1 year"
# 视频和音频 - 长缓存
ExpiresByType video/mp4 "access plus 1 year"
ExpiresByType video/webm "access plus 1 year"
ExpiresByType audio/mpeg "access plus 1 year"
ExpiresByType audio/ogg "access plus 1 year"
# 文档文件 - 中等缓存
ExpiresByType application/pdf "access plus 1 month"
ExpiresByType application/xml "access plus 1 hour"
ExpiresByType application/json "access plus 0 seconds"
# 数据文件 - 不缓存
ExpiresByType text/xml "access plus 0 seconds"
</IfModule>
时间格式说明 #
text
┌─────────────────────────────────────────────────────────────┐
│ Expires 时间格式 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 基准时间: │
│ access 访问时间 │
│ now 等同于 access │
│ modification 文件修改时间 │
│ │
│ 时间单位: │
│ years 年 │
│ months 月 │
│ weeks 周 │
│ days 天 │
│ hours 小时 │
│ minutes 分钟 │
│ seconds 秒 │
│ │
│ 示例: │
│ "access plus 1 month" │
│ "access plus 1 year" │
│ "access plus 2 weeks 3 days" │
│ "modification plus 1 month" │
│ "access plus 0 seconds" # 不缓存 │
│ │
└─────────────────────────────────────────────────────────────┘
mod_headers 配置 #
apache
# ============================================
# mod_headers Cache-Control 配置
# ============================================
<IfModule mod_headers.c>
# HTML - 不缓存
<FilesMatch "\.(html|htm)$">
Header set Cache-Control "no-cache, no-store, must-revalidate"
Header set Pragma "no-cache"
Header set Expires 0
</FilesMatch>
# CSS/JS - 强缓存
<FilesMatch "\.(css|js)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
# 图片 - 强缓存
<FilesMatch "\.(jpg|jpeg|png|gif|svg|webp|ico)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
# 字体 - 强缓存
<FilesMatch "\.(woff|woff2|ttf|otf|eot)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
# 视频/音频 - 强缓存
<FilesMatch "\.(mp4|webm|mp3|ogg|wav)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
# PDF - 中等缓存
<FilesMatch "\.pdf$">
Header set Cache-Control "public, max-age=2592000"
</FilesMatch>
# JSON/XML - 不缓存
<FilesMatch "\.(json|xml)$">
Header set Cache-Control "no-cache, no-store, must-revalidate"
</FilesMatch>
</IfModule>
Cache-Control 指令说明 #
text
┌─────────────────────────────────────────────────────────────┐
│ Cache-Control 指令 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 可缓存性: │
│ public 可被任何缓存存储 │
│ private 仅浏览器可缓存 │
│ no-cache 使用前需验证 │
│ no-store 不缓存 │
│ │
│ 过期时间: │
│ max-age=秒 最大缓存时间 │
│ s-maxage=秒 共享缓存最大时间 │
│ max-stale=秒 可接受过期时间 │
│ min-fresh=秒 最小新鲜时间 │
│ │
│ 重新验证: │
│ must-revalidate 必须重新验证 │
│ proxy-revalidate 代理必须重新验证 │
│ immutable 资源永不改变 │
│ no-transform 不转换响应内容 │
│ │
│ 常用组合: │
│ 不缓存:no-cache, no-store, must-revalidate │
│ 强缓存:public, max-age=31536000, immutable │
│ 协商缓存:no-cache, max-age=0 │
│ │
└─────────────────────────────────────────────────────────────┘
ETag 配置 #
ETag 基础 #
apache
# ============================================
# ETag 配置
# ============================================
# 启用 ETag
FileETag MTime Size
# ETag 组成
# INode 文件 inode 号
# MTime 修改时间
# Size 文件大小
# 完整配置
FileETag INode MTime Size
# 禁用 ETag(如果使用 Last-Modified)
# FileETag None
# 为静态资源设置 ETag
<Directory /var/www/html/static>
FileETag MTime Size
</Directory>
ETag vs Last-Modified #
apache
# ============================================
# ETag 与 Last-Modified 对比
# ============================================
# ETag 方式
# 优点:精确识别文件变化
# 缺点:需要计算,占用资源
FileETag MTime Size
# Last-Modified 方式
# 优点:简单,性能好
# 缺点:只能精确到秒
# 默认启用,无需配置
# 组合使用
<Directory /var/www/html/static>
FileETag MTime Size
# Last-Modified 自动启用
</Directory>
服务器缓存配置 #
启用 mod_cache #
bash
# Ubuntu/Debian
sudo a2enmod cache
sudo a2enmod cache_disk
sudo a2enmod cache_socache
sudo systemctl restart apache2
磁盘缓存配置 #
apache
# ============================================
# mod_cache_disk 磁盘缓存
# ============================================
# 缓存根目录
CacheRoot /var/cache/apache2/mod_cache_disk
# 目录层级
CacheDirLevels 2
CacheDirLength 1
# 最大缓存大小
CacheMaxFileSize 10000000
CacheMinFileSize 1
# 缓存配置
<IfModule mod_cache.c>
<IfModule mod_cache_disk.c>
CacheRoot /var/cache/apache2/proxy
CacheDirLevels 2
CacheDirLength 1
CacheMaxFileSize 10000000
</IfModule>
# 启用缓存
CacheQuickHandler on
# 缓存锁
CacheLock on
CacheLockPath /tmp/cachelock
CacheLockMaxAge 5
</IfModule>
代理缓存配置 #
apache
# ============================================
# 反向代理缓存配置
# ============================================
<IfModule mod_cache.c>
<IfModule mod_cache_disk.c>
CacheRoot /var/cache/apache2/proxy
CacheDirLevels 2
CacheDirLength 1
</IfModule>
# 启用缓存
CacheQuickHandler on
</IfModule>
<VirtualHost *:80>
ServerName api.example.com
# 启用缓存
<Location />
CacheEnable disk
CacheHeader on
CacheDefaultExpire 3600
CacheMaxExpire 86400
CacheLastModifiedFactor 0.5
CacheIgnoreHeaders Set-Cookie
CacheIgnoreNoLastMod On
</Location>
# 代理配置
ProxyPass / http://localhost:3000/
ProxyPassReverse / http://localhost:3000/
</VirtualHost>
缓存条件控制 #
apache
# ============================================
# 缓存条件控制
# ============================================
<VirtualHost *:80>
ServerName example.com
# 仅缓存 GET 请求
<Location />
CacheEnable disk
CacheAllowMethods GET
</Location>
# 排除特定 URL
<Location /api>
CacheDisable
</Location>
<Location /admin>
CacheDisable
</Location>
# 排除带查询参数的请求
CacheIgnoreQueryString On
# 忽略特定头
CacheIgnoreHeaders Set-Cookie Authorization
</VirtualHost>
.htaccess 缓存配置 #
apache
# ============================================
# .htaccess 缓存配置
# ============================================
# 启用过期控制
<IfModule mod_expires.c>
ExpiresActive On
# 图片
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
# CSS/JS
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
# 字体
ExpiresByType font/woff "access plus 1 year"
ExpiresByType font/woff2 "access plus 1 year"
</IfModule>
# Cache-Control 头
<IfModule mod_headers.c>
<FilesMatch "\.(jpg|jpeg|png|gif|svg|css|js|woff|woff2)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
<FilesMatch "\.(html|htm)$">
Header set Cache-Control "no-cache, no-store, must-revalidate"
</FilesMatch>
</IfModule>
缓存验证 #
条件请求 #
text
┌─────────────────────────────────────────────────────────────┐
│ 条件请求 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 客户端缓存验证流程: │
│ │
│ 1. 首次请求 │
│ 客户端 ──> 服务器 │
│ 服务器返回内容 + ETag/Last-Modified │
│ 客户端缓存内容 │
│ │
│ 2. 再次请求(使用 If-None-Match) │
│ 客户端 ──> 服务器 │
│ If-None-Match: "etag-value" │
│ │
│ 3. 服务器验证 │
│ - ETag 匹配 ──> 304 Not Modified │
│ - ETag 不匹配 ──> 200 OK + 新内容 │
│ │
│ 或使用 If-Modified-Since: │
│ If-Modified-Since: Wed, 21 Oct 2026 07:28:00 GMT │
│ │
└─────────────────────────────────────────────────────────────┘
验证缓存配置 #
bash
# 测试缓存配置
curl -I https://example.com/style.css
# 输出应包含
# Cache-Control: public, max-age=31536000, immutable
# ETag: "abc123"
# Last-Modified: Wed, 21 Oct 2026 07:28:00 GMT
# 测试条件请求
curl -I -H 'If-None-Match: "abc123"' https://example.com/style.css
# 应返回 304 Not Modified
缓存最佳实践 #
静态资源缓存策略 #
text
┌─────────────────────────────────────────────────────────────┐
│ 静态资源缓存策略 │
├─────────────────────────────────────────────────────────────┤
│ │
│ HTML 文件: │
│ Cache-Control: no-cache │
│ 原因:需要及时更新 │
│ │
│ CSS/JS(带版本号): │
│ Cache-Control: public, max-age=31536000, immutable │
│ 原因:文件名变化即新资源 │
│ │
│ 图片/字体: │
│ Cache-Control: public, max-age=31536000, immutable │
│ 原因:很少变化 │
│ │
│ API 响应: │
│ Cache-Control: no-cache 或 no-store │
│ 原因:数据实时性要求高 │
│ │
└─────────────────────────────────────────────────────────────┘
版本化静态资源 #
apache
# ============================================
# 版本化静态资源配置
# ============================================
# 方案 1:查询参数版本
# /style.css?v=1.0.0
# 浏览器会认为是新资源
# 方案 2:文件名版本
# /style.v1.0.0.css 或 /v1.0.0/style.css
# 配置长缓存
<FilesMatch "\.v[0-9]+\.[0-9]+\.[0-9]+\.(css|js)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
# 方案 3:内容哈希
# /style.abc123.css
<FilesMatch "\.[a-f0-9]{8,}\.(css|js)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
完整配置示例 #
apache
# ============================================
# 完整缓存配置示例
# ============================================
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/html
# 浏览器缓存
<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 1 month"
ExpiresByType text/html "access plus 0 seconds"
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType font/woff "access plus 1 year"
ExpiresByType font/woff2 "access plus 1 year"
</IfModule>
# Cache-Control 头
<IfModule mod_headers.c>
<FilesMatch "\.(html|htm)$">
Header set Cache-Control "no-cache, no-store, must-revalidate"
</FilesMatch>
<FilesMatch "\.(css|js|jpg|jpeg|png|gif|svg|woff|woff2)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
</IfModule>
# ETag
FileETag MTime Size
<Directory /var/www/html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
下一步 #
掌握了缓存配置后,继续学习 Gzip 压缩,了解如何配置响应压缩提升传输效率!
最后更新:2026-03-29