一、分类
- 三态缓存rfc2616
- 双态键/值共享对象缓存
- 特殊文件缓存
二、三态缓存
- 状态
- fresh 新鲜,直接从缓存获取内容返回,不经处理
- stale 过期 ,请求服务器来确认,服务器返回未过期状态码或者新内容。服务器响应为5xx内部错误或者已经有其他请求在刷新当前缓存过程中时,返回当前过期缓存,并添加一个警告响应头信息(也不是个啥)
- non existent 不存在,(缓存不存在时就请求获取被,也没说,说了缓存满了怎么办)当缓存满了可以使用htcacheclean工具(源码安装时bin目录里就有)执行清理,或者整成守护进程维持缓存,工具会优先删除已过期缓存。
- 服务器交互
根据CacheQuickHandler设置可分为快速处理、正常处理两个模式。默认为on快速处理模式,对于需要授权验证的资源可改为off正常模式,此时进行完整的请求处理流程。
- 快速处理模式
此阶段发生在请求服务器处理请求的早期,在缓存中发现内容直接返回,几乎绕过所有请求解析。效率性能高,但是由于直接返回,请求的身份和授权验证将被绕过。具有authorization请求头的响应不会被缓存。(也就是说,受限资源请求都加此头信息被?那一个后台的所有请求都要加。) - 正常处理模式
此阶段发生在服务器请求处理后期,非常灵活,可以精确的出现在过滤器链中某个节点,且可以在缓存响应返回前进行过滤或这个性化处理。
- 改善缓存命中
在虚拟主机设置中,如果有多个别名时,把UseCanonicalName 设置为on,会仅根据ServerName设置的主机名、端口名来建立自引用,从而避免产生多份份缓存, - 新鲜生命周期
- 应该有Cache-Control头的max-age、s-maxage字段来指定生命周期或者Expires头(单位是秒,max-age、expires设置生命周期时间,s-maxage可以覆盖前两者,仅作用于共享缓存,如代理的缓存)
- 请求、响应头中生命周期定义冲突时,短的那个生效。
- 请求或响应没有缓存生命周期头设定时,采用CacheDefaultExpire命令设置值(单位秒),默认1小时。
- 当响应只包含Last-Modified头信息时,将自动推导过期时间,公式为:过期时间=当前时间+当前距离Last-Modified时间*自定义系数,自定义系数由CacheLastModifiedFactor指定设定,默认0.1.
- 对于本地内容(应该是直接存在文件的,如css、js啥的)可以使用mod_expires模块来指定max-age和Expires头信息。(使用ExpiresActive指令开启当前层级有效期控制,用ExpiresDefault设置默认过期时间,用ExpiresByType按类型设置过期时间,后者可覆盖前者。有效期基于访问或修改时间。指令值格式为Axxx、Mxxx,或者间隔区间语法access plus 1 day plus 2months)
- 最大缓存时间可以用CacheMaxExpire进行控制,默认一天(说设置后,即使文档中指定了过期时间,也按此计算,应该是文档中设置的过期时间大于此时间时,按此时间计算)
三、条件请求
- 当内容过期时变为stale状态,响应请求变为条件请求。
- 缓存响应中若存在etag头信息,则将把If-None-Match头添加到原服务器的请求中。缓存响应中如果存在Last-Modified头,则添加If-Modified-Since头到服务器请求中。
- 服务器收到请求后判断请求对应资源的etag或Last-Modified参数是否改变,未改变时返回304响应。缓存将刷新器生命周期。
- 内容已改变时,正常响应。
- 如果服务器不支持条件请求,则会像简单的两态缓存一样运行。
四、可以被缓存的请求
- 必须通过CacheEnable和CacheDisable来开启或关闭特定url。
- 若响应状态码非200,203,300,301或410,则必须指定Expires或者Cache-Control头
- 必须是Get请求。
- 如果请求中带有Authorization头,那么请求头中还要有s-maxage、must-ralidate或者public等Cache-Control头才会被缓存。
- 若Get请求包含查询参数时,仅当响应中明确包含Expires头或者Cache-Control头的max-age、s-maxage命令才会被缓存。
- 响应状态码为200时,也必须至少包含Etag、Last-Modified或者Expires头,或者Cache-Control头的max-age、s-maxage指令,才会被缓存。也可以通过CacheIgnoreNoLastMod来取消此限制。
- 带有Cache-Control的private指令的响应不会被缓存。可以通过CacheStorePrivate来放开此限制。
- 带有包含*的Vary头的响应不会被缓存。
五、不应该被缓存的
- 应该由客户端或服务器通过中却设定Cache-Control头来决定是否缓存。mod_cache应该单独用来满足二者的需要。
- 不应该缓存时间敏感的内容,这些内容应该由内容本身通过Cache-Control声明自身不被缓存。
- 对于经常变化的内容,也可以被缓存,但是原始服务器应该完成条件请求支持,以确保响应不是定期生成的方式。
- 可以使用vary响应头来缓存根据请求头变化的响应。
六、变量/协议 内容
缓存可以根据vary设置的头信息来区别存储、返回响应信息
七、缓存设置举例
1. 缓存到磁盘
- 需要模块mod_cache、mod_cache_disk
- 配置
CacheRoot ‘var/cache/apache/’ #缓存根目录
CacheEnable disk / #开启/路径下所有url的缓存,以disk方式
CacheDirLevels 2 #缓存目录层级,缓存目录结构有几层
CacheDirLength 1 #每层目录名称的字符长度,每一字符有64种可能。决定每层有多少目录。
- 每个url会存储两个文件: .header文件存储meta信息,.data文件存储数据信息,当使用Vary头时会创建一个.vary目录,目录中包含多个根据不同协议产生的.data文件。
- 维护缓存
可以以守护进程的方式运行htcacheclean,或者利用cron周期运行,后者需要自行选择合适的运行周期,以避免同时运行多个实例。清理时应该留有足够成长空间。
2. 缓存到memcache
- 需要mod_cache_socache模块和mod_cache模块
- 典型配置
CacheEnable socache / #开启socache方式 /url的缓存
CacheSocache memcache:memcd.example.com:11211 #...
(。。。)
八、常规两态 键值 共享对象缓存
可以利用socache模块接口实现授权缓存ssl对话缓存等(。。。)
九、特殊文件缓存
- 利用mod_file_cache模块可以在服务器启动时就缓存特定文件,有利于快速打开那些打开缓慢的文件。
- CacheFile命令,缓存时只缓存文件描述符(也不是个啥,像是个资源句柄),所以对于文件的更改不会被再次捕获(就是内容一直保持打开时的样子吗,还自带版本管理么,没有缓存内容怎么做到版本管理的)
- 由于内存存储响应更快速,MMapFile指令,可以通过调用系统命令mmap,把文件映射缓存到内容中。与CacheFile一样缓存后不会捕获文件后续更改。每个httpd子进程会复制缓存内容,所以要注意缓存文件的大小。