apache mod_cache in v2.2 - enable cache based on url
- by Janning
We are using apache2.2 as a front-end server with application servers as reverse proxies behind apache.
We are using mod_cache for some images and enabled it like this:
<IfModule mod_disk_cache.c>
CacheEnable disk /
CacheRoot /var/cache/apache2/mod_disk_cache
CacheIgnoreCacheControl On
CacheMaxFileSize 2500000
CacheIgnoreURLSessionIdentifiers jsessionid
CacheIgnoreHeaders Set-Cookie
</IfModule>
The image urls vary completely and have no common start pattern, but they all end in ".png". Thats why we used the root in CacheEnable /
If not served from the cache, the request is forwarded to an application server via reverse proxy. So far so good, cache is working fine.
But I really only need to cache all image request ending in ".png". My above configuration still works as my application server send an appropriate Cache-Control: no-cache header on the way back to apache. So most pages send a no-cache header back and they get not cached at all. My ".png" responses doesn't send a Cache-Control header so apache is only going to cache all urls with ".png". Fine.
But when a new request enters apache, apache does not know that only .png requests should be considered, so every request is checking a file on disk (recorded with 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)
I don't want to have apache going to disk every request, as the majority of requests are not cached at all. And we have up to 10.000 request/s at peak time. Sometimes our read IO wait spikes. It is not getting really slow, but we try to tweak it for better performance.
In apache 2.4 you can say:
<LocationMatch .png$>
CacheEnable disk
</LocationMatch>
This is not possible in 2.2 and as I see no backports for debian I am not going to upgrade.
So I tried to tweak apache2.2 to follow my rules:
<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>
The idea is to let apache decide to serve request from cache based on Cache-control header (CacheIgnoreCacheControl default to off). And before simply set a RequestHeader based on the request. If it is not an image request, set a Cache-control header, so it should bypass the cache at all.
This does not work, I guess because of late processing of RequestHeader directive, see https://httpd.apache.org/docs/2.2/mod/mod_headers.html#early
I can't add early processing as "early" keyword can't be used together with a conditional "env=!image"
I can't change the url requesting the images and I know there are of course other solutions. But I am only interested in configuring apache2.2 to reach my goal.
Does anybody has an idea how to achieve my goal?