我们使用 apache2.2 作为前端服务器,并使用应用程序服务器作为 apache 后面的反向代理。
我们正在使用mod_cache
一些图像并像这样启用它:
<IfModule mod_disk_cache.c>
CacheEnable disk /
CacheRoot /var/cache/apache2/mod_disk_cache
CacheIgnoreCacheControl On
CacheMaxFileSize 2500000
CacheIgnoreURLSessionIdentifiers jsessionid
CacheIgnoreHeaders Set-Cookie
</IfModule>
图像 URL 完全不同,没有共同的起始模式,但它们都以“.png”结尾。这就是为什么我们在CacheEnable /
如果缓存无法提供服务,请求将通过反向代理转发到应用服务器。到目前为止一切顺利,缓存运行良好。
但实际上我只需要缓存所有以“.png”结尾的图像请求。我的上述配置仍然有效,因为我的应用服务器在返回 apache 的途中发送了适当的 Cache-Control: no-cache 标头。因此大多数页面都会返回 no-cache 标头,并且根本不会被缓存。我的“.png”响应不会发送 Cache-Control 标头,因此 apache 只会缓存所有以“.png”结尾的 URL。很好。
但是当一个新的请求进入 apache 时,apache 不知道只应考虑 .png 请求,因此每个请求都会检查磁盘上的文件(用 记录strace -e trace=file -p pid
):
[pid 19063] open("/var/cache/apache2/mod_disk_cache/zK/q8/Kd/g6OIv@woJRC_ba_A.header", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
我不想让 Apache 每次请求都转到磁盘,因为大多数请求根本没有缓存。而且我们在高峰时间每秒最多有 10,000 个请求。有时我们的读取 IO 等待时间会达到峰值。它并没有变得很慢,但我们尝试对其进行调整以获得更好的性能。
在 Apache 2.4 中你可以说:
<LocationMatch .png$>
CacheEnable disk
</LocationMatch>
在 2.2 中这是不可能的,而且由于我看不到 Debian 的反向移植,所以我不会升级。
因此我尝试调整 apache2.2 以遵循我的规则:
<IfModule mod_disk_cache.c>
SetEnvIf Request_URI "\.png$" image
RequestHeader unset Cache-Control
RequestHeader append Cache-Control no-cache env=!image
CacheEnable disk /
CacheRoot /var/cache/apache2/mod_disk_cache
#CacheIgnoreCacheControl on
CacheMaxFileSize 2500000
CacheIgnoreURLSessionIdentifiers jsessionid
CacheIgnoreHeaders Set-Cookie
</IfModule>
这个想法是让 apache 根据 Cache-control 标头决定从缓存中处理请求(CacheIgnoreCacheControl 默认为关闭)。之前只需根据请求设置一个 RequestHeader。如果不是图像请求,则设置一个 Cache-control 标头,这样它应该完全绕过缓存。
这不起作用,我猜是因为 RequestHeader 指令的处理较晚,请参阅https://httpd.apache.org/docs/2.2/mod/mod_headers.html#early
我无法添加早期处理,因为“early”关键字不能与条件“env=!image”一起使用
我无法更改请求图像的 URL,我知道当然还有其他解决方案。但我只对配置 apache2.2 来实现我的目标感兴趣。
有人知道如何实现我的目标吗?
答案1
https://httpd.apache.org/docs/2.2/mod/mod_cache.html#cachedisable
可以设置 no-cache 环境变量来禁用 2.2.12 及更高版本中更细粒度的资源集上的缓存。
因此,你应该能够禁用除以 .png 结尾的请求之外的所有内容的缓存
SetEnvIf Request_URI !\.png$ no-cache