在我解释我的流程之前,有一个快速问题:如果在反向代理模式下配置,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
谢谢,我将非常感激任何帮助。