apache mod_cache in v2.2 - enable cache based on url

Posted by Janning on Server Fault See other posts from Server Fault or by Janning
Published on 2012-06-22T15:21:10Z Indexed on 2013/10/21 3:57 UTC
Read the original article Hit count: 524

Filed under:
|

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?

© Server Fault or respective owner

Related posts about apache2

Related posts about mod-cache