mod_cache 如何与“must-revalidate”和“max-age”一起工作?

mod_cache 如何与“must-revalidate”和“max-age”一起工作?

在我解释我的流程之前,有一个快速问题:如果在反向代理模式下配置,mod_cache 是否只能在 max-age 过期时使用 if-none-match 执行重新验证?

我的目标是减少对原始服务器的重新验证请求的数量。

例如:第一个请求到达源服务器,然后 mod_cache 根据 header cache-control: max-age 将响应保存到缓存中。并且只有当 max-age 过期时,mod_cache 才会使用 if-none-match 重新验证。

目前,mod_cache 重新验证每个请求,无论是否定义了 max-age。

我的配置是 Apache 2.4.3(Windows),在 Linux 上我看到了相同的行为,如下所示。

    
   服务器名称代理.lo
   ProxyRequests 关闭    
   ProxyPreserveHost 关闭

   标头设置变化“接受,内容类型,内容编码,接受语言”

   RequestHeader 设置 X-Forwarded-Proto "http"

   # 修改用户代理的标头
   标头设置 Cache-Control“private、no-cache、no-store、no-transform”

   CacheQuickHandler 关闭

   CacheDefaultExpire 300

   # 源服务器不提供最后修改时间
   CacheIgnoreNoLastMod 开启
   CacheIgnoreCacheControl 开启

   # 原始服务器定义缓存控制:私有,不存储仅适用于用户代理
   # 因此,我想忽略代理服务器上的这些标头。
   CacheStorePrivate 开启
   CacheStoreNoStore 开启

   CacheEnable 磁盘 /
   CacheRoot“C:/Apache.Cache”
   CacheDirLevels 5
   CacheDirLength 4

   CacheMinExpire 15

   CacheDetailHeader 开启
   CacheHeader 开启

   KeepAlive 关闭

   ProxyPass/http://origin.lo/
   ProxyPassReverse / http://origin.lo/

此外,我已打开调试日志级别,以查看 mod_cache 如何处理缓存内容:我提供此信息是为了表明 mod_proxy 始终认为内容不新鲜。为什么?我提供此信息是为了表明 mod_proxy 始终认为内容不新鲜。为什么?提供了 max-age(见下文)。

[2012 年 11 月 4 日星期日 11:58:42.899890] [cache:debug] [pid 6492:tid 1400] cache_storage.c(624):[客户端 192.168.1.100:63741] AH00698:缓存:实体 /testpage 的键?(null) 是 http://proxy.lo/testpage?
[2012 年 11 月 4 日星期日 11:58:42.899890] [cache_disk:debug] [pid 6492:tid 1400] mod_cache_disk.c(569):[客户端 192.168.1.100:63741] AH00709:调用缓存的 URL 信息标头 http://proxy.lo/testpage?
[2012 年 11 月 4 日星期日 11:58:42.899890] [cache_disk:debug] [pid 6492:tid 1400] mod_cache_disk.c(865):[客户端 192.168.1.100:63741] AH00720:是否已调用 URL http://proxy.lo/testpage 的标头?
[2012 年 11 月 4 日星期日 11:58:42.899890] [cache:debug] [pid 6492:tid 1400] cache_storage.c(320): [客户端 192.168.1.100:63741] AH00695: /testpage 的缓存响应不新鲜。添加/替换条件请求标头。
[2012 年 11 月 4 日星期日 11:58:42.899890] [cache:debug] [pid 6492:tid 1400] mod_cache.c(414):[客户端 192.168.1.100:63741] AH00757:为 /testpage 添加 CACHE_SAVE 过滤器
[2012 年 11 月 4 日星期日 11:58:42.899890] [cache:debug] [pid 6492:tid 1400] mod_cache.c(448):[客户端 192.168.1.100:63741] AH00759:为 /testpage 添加 CACHE_REMOVE_URL 过滤器
[2012 年 11 月 4 日星期日 11:58:42.899890] [proxy:debug] [pid 6492:tid 1400] mod_proxy.c(1068):[客户端 192.168.1.100:63741] AH01143:正在运行方案 http 处理程序(尝试 0)
[2012 年 11 月 4 日星期日 11:58:42.899890] [proxy:debug] [pid 6492:tid 1400] proxy_util.c(1976):AH00942:HTTP:已获取 (origin.lo) 的连接
[2012 年 11 月 4 日星期日 11:58:42.899890] [proxy:debug] [pid 6492:tid 1400] proxy_util.c(2029):[客户端 192.168.1.100:63741] AH00944:将 http://origin.lo/testpage 连接到 origin.lo:80
[2012 年 11 月 4 日星期日 11:58:42.901890] [proxy:debug] [pid 6492:tid 1400] proxy_util.c(2151):[客户端 192.168.1.100:63741] AH00947:已将 /testpage 连接到 origin.lo:80
[2012 年 11 月 4 日星期日 11:58:42.901890] [proxy:debug] [pid 6492:tid 1400] proxy_util.c(2554):AH00962:HTTP:已完成与 192.168.1.100:80 (origin.lo) 的连接
[2012 年 11 月 4 日星期日 11:58:42.903890] [proxy:debug] [pid 6492:tid 1400] proxy_util.c(1991):AH00943:http:已释放 (origin.lo) 的连接
[2012 年 11 月 4 日星期日 11:58:42.903890] [headers:debug] [pid 6492:tid 1400] mod_headers.c(800):AH01502:headers:ap_headers_output_filter()
[2012 年 11 月 4 日星期日 11:58:42.903890] [cache:debug] [pid 6492:tid 1400] mod_cache.c(1190):[客户端 192.168.1.100:63741] AH00769:缓存:缓存 url:/testpage
[2012 年 11 月 4 日星期日 11:58:42.903890] [cache:debug] [pid 6492:tid 1400] mod_cache.c(1196):[客户端 192.168.1.100:63741] AH00770:cache:删除 CACHE_REMOVE_URL 过滤器。
[2012 年 11 月 4 日星期日 11:58:42.904890] [cache_disk:debug] [pid 6492:tid 1400] mod_cache_disk.c(1318):[客户端 192.168.1.100:63741] AH00737:commit_entity:URL http://proxy.lo/testpage 的标头和正文?已缓存。

第一个没有使用 mod_proxy 的请求到源服务器http://origin.lo/

获取 http://origin.lo/testpage HTTP/1.1
主机:origin.lo
连接:保持连接
用户代理:Mozilla/5.0(Windows NT 6.1;WOW64)AppleWebKit/537.4(KHTML,如 Gecko)Chrome/22.0.1229.94 Safari/537.4
接受:application/json
接受编码:gzip,deflate,sdch
接受语言: en-US,en;q=0.8
接受字符集:ISO-8859-1,utf-8;q=0.7,*;q=0.3

没有使用 mod_proxy 的源的第一个响应

HTTP/1.1 200 正常
缓存控制:必须重新验证、代理重新验证、最大年龄 = 30
内容类型:application/json;charset=utf-8
ETag:“7cf651e2-176f-4ac1-808e-0e0c17cfd0a2”
服务器:Microsoft-IIS/7.5
X-AspNet-版本:4.0.30319
X-Powered-By:ASP.NET
日期:2012 年 11 月 4 日星期日 10:11:01 GMT
内容长度:1877

因此,我假设重新验证必须在成功响应后 30 秒内发生。对吗?

我们来检查一下:)

在 30 秒内,Google Chrome 没有向原始服务器发出任何请求来重新验证请求,而是从本地缓存返回响应。

当 max-age 过期时,Google Chrome 会执行重新验证请求:

获取 http://origin.lo/testpage HTTP/1.1
主机:origin.lo
连接:保持连接
缓存控制:max-age=0
用户代理:Mozilla/5.0(Windows NT 6.1;WOW64)AppleWebKit/537.4(KHTML,如 Gecko)Chrome/22.0.1229.94 Safari/537.4
接受:application/xml
如果没有匹配:“7cf651e2-176f-4ac1-808e-0e0c17cfd0a2”
接受编码:gzip,deflate,sdch
接受语言: en-US,en;q=0.8
接受字符集:ISO-8859-1,utf-8;q=0.7,*;q=0.3

和响应:

HTTP/1.1 304 未修改
缓存控制:必须重新验证、代理重新验证、最大年龄 = 30
ETag:“7cf651e2-176f-4ac1-808e-0e0c17cfd0a2”
服务器:Microsoft-IIS/7.5
X-AspNet-版本:4.0.30319
X-Powered-By:ASP.NET
日期:2012 年 11 月 4 日星期日 10:16:20 GMT

如您所见,一切按预期进行。仅当 max-age 过期时,用户代理才会重新验证请求。

现在让我们尝试通过 mod_proxy 执行以下流程(参见上面的配置)。

第一个请求:

获取 http://proxy.lo/testpage HTTP/1.1
主机:proxy.lo
连接:保持连接
用户代理:Mozilla/5.0(Windows NT 6.1;WOW64)AppleWebKit/537.4(KHTML,如 Gecko)Chrome/22.0.1229.94 Safari/537.4
接受:application/json
接受编码:gzip,deflate,sdch
接受语言: en-US,en;q=0.8
接受字符集:ISO-8859-1,utf-8;q=0.7,*;q=0.3

答复是:

HTTP/1.1 200 正常
日期:2012 年 11 月 4 日星期日 10:23:36 GMT
服务器:Apache
缓存控制:私有、无缓存、无存储、无转换
内容类型:application/json;charset=utf-8
ETag:“7cf651e2-176f-4ac1-808e-0e0c17cfd0a2”
内容长度:1932
变化:接受、内容类型、内容编码、接受语言
X-Cache:来自 proxy.lo 的 MISS
X-Cache-Detail:“缓存未命中:尝试保存实体”来自 proxy.lo
连接:关闭

好的,让我们看看磁盘缓存,并尝试看看请求和响应是如何存储的。(我剪切了二进制数据)

http://proxy.lo/testpage?
缓存控制:私有、无缓存、无存储、无转换
内容类型:application/json;charset=utf-8
ETag:“7cf651e2-176f-4ac1-808e-0e0c17cfd0a2”
日期:2012 年 11 月 4 日星期日 10:27:15 GMT
内容长度:1932
变化:接受、内容类型、内容编码、接受语言

主机:proxy.lo
用户代理:Mozilla/5.0(Windows NT 6.1;WOW64)AppleWebKit/537.4(KHTML,如 Gecko)Chrome/22.0.1229.94 Safari/537.4
接受:application/json
接受编码:gzip,deflate,sdch
接受语言: en-US,en;q=0.8
接受字符集:ISO-8859-1,utf-8;q=0.7,*;q=0.3
X-Forwarded-Proto: http
缓存控制:max-age=300,必须重新验证
X-转发-针对:192.168.1.100
X-Forwarded-Host: proxy.lo
X-Forwarded-Server: origin.lo

好的,我们看到了什么?我们看到第一个请求是在 max-age=300 和 must-revalidate 的情况下执行的

好的,看起来不错,对于我来说,让我们执行下一个调用:

获取 http://proxy.lo/testpage HTTP/1.1
主机:proxy.lo
连接:保持连接
用户代理:Mozilla/5.0(Windows NT 6.1;WOW64)AppleWebKit/537.4(KHTML,如 Gecko)Chrome/22.0.1229.94 Safari/537.4
接受:application/json
接受编码:gzip,deflate,sdch
接受语言: en-US,en;q=0.8
接受字符集:ISO-8859-1,utf-8;q=0.7,*;q=0.3

来自 mod_proxy 的第二个响应:

HTTP/1.1 200 正常
日期:2012 年 11 月 4 日星期日 10:31:58 GMT
服务器:Apache
缓存控制:私有、无缓存、无存储、无转换
ETag:“7cf651e2-176f-4ac1-808e-0e0c17cfd0a2”
内容长度:1932
变化:接受、内容类型、内容编码、接受语言
X-Cache:来自 proxy.lo 的重新验证
X-Cache-Detail:“条件缓存命中:实体已刷新”来自 proxy.lo
连接:关闭
内容类型:application/json;charset=utf-8

所以,我的问题是:为什么 mod_proxy 会对每个请求执行重新验证,而不管 max-age 是否定义?

NB Apache 2.4.3

谢谢,我将非常感激任何帮助。

相关内容