1

I'm serving static files (images, javascript, css files) from a (hopefully) cookieless domain also mapped to my cloudcontrol deployment. Here are the request and reponse headers. I see no cookie header in the request, ETag and date check should satisfy, so I would expect that the varnish proxy in front of the cloudcontrol deployment would fetch the request and serve it, but everytime I try it out all static files are served from the Apache processes according to the response header. Any tipps appreciated.

Request URL:http://static.hotelpress.mobi/bundles/viermediamagazine/icons/social/Facebook_64.png
Request Method:GET
Status Code:304 Not Modified

Request Headers

Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
Cache-Control:max-age=0
Connection:keep-alive
Host:static.hotelpress.mobi
If-Modified-Since:Sat, 20 Apr 2013 18:23:31 GMT
If-None-Match:"6008d436-1108-4daceeec74ec0"
Referer:---stripped out or my boss kills me---
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31

Response Headers

Accept-Ranges:bytes
Age:0
Connection:keep-alive
Date:Sat, 20 Apr 2013 18:31:33 GMT
ETag:"6008d436-1108-4daceeec74ec0"
Last-Modified:Sat, 20 Apr 2013 18:23:31 GMT
Server:Apache
Via:1.1 varnish
X-Varnish:995972028
X-varnish-cache:MISS
Shannera
  • 13
  • 3

3 Answers3

2

Assuming that Varnish is passing through all your Apache headers, it appears that you are not setting any headers telling Varnish to cache.

Varnish does cache silently for 2 minutes by default with no headers, but you probably want more than that.

You should also remove the Etag, for the reasons you say. More information on Etags is here.

If you have fingerprinted assets (per deploy/change), you should set those in Apache for 1 year.

Any others can be as long as you can stand (remembering that this may stop you frequently updating those assets, because they may be cached somewhere).

Here are the lines you need in apache:

<LocationMatch "^/path/to/fingerprinted/assets/.*$">
    Header unset ETag
    FileETag None
    # RFC says only cache for 1 year
    ExpiresActive On
    ExpiresDefault "access plus 1 year"
    Header append Cache-Control "public"
</LocationMatch>

and for others:

<LocationMatch "^/bundles/viermediamagazine/icons/.*$">
    Header unset ETag
    FileETag None
    ExpiresActive On
    ExpiresDefault "access plus 1 week"
    Header append Cache-Control "public"
</LocationMatch>

You can use as many locations as you want - just make sure they do not overlap!

Richard Hulse
  • 10,383
  • 2
  • 33
  • 37
  • One thing to add is that cloudControl (currently) has three loadbalancers running (according to dns), so there are three seperate Varnishes with seperate caches. – Denis Cornehl Apr 22 '13 at 07:09
  • Thanks for the detailed explanations, will try them out. – Shannera Apr 22 '13 at 12:29
  • Just a short followup after trying all the stuff out: if you add a folder structure .buildpack/apache/conf (files to be included has to be named with the conf suffix) and .buildpack/php/conf (files to be included has to be named with the ini suffix), you can add these directives and special settings, and they will be honored - which means Richards solution works fine for me. – Shannera May 13 '13 at 20:29
1

The example request you posted contains

Cache-Control:max-age=0

which prevents cached answers iirc. You could also try if setting a Cache-Control: max-age=<x> header in your response helps.

Stefan Friesel
  • 823
  • 5
  • 19
  • That could be a reason, at least it should force the cache to revalidate. On the other hand, the request headers come from the browser, and I can't really alter this. One other problem I became aware when searching on the net for similar problems: ETags are most likely generated with some unique component of the server, so in a clustered environment with many apache processes it is most likely you get different ETags from request to request... – Shannera Apr 20 '13 at 22:55
0

Extending the other answers: Here's a sample request to an app on cloudControl, that caches (when the ?c=1). In any case send requests multiple times until you get hits consistently to make sure all Varnish instances have cached the response.

$ curl -v http://impresstw.cloudcontrolled.com/?c=1
* About to connect() to impresstw.cloudcontrolled.com port 80 (#0)
*   Trying 46.137.184.215...
* connected
* Connected to impresstw.cloudcontrolled.com (46.137.184.215) port 80 (#0)
> GET /?c=1 HTTP/1.1
> User-Agent: curl/7.27.0
> Host: impresstw.cloudcontrolled.com
> Accept: */*
> 
< HTTP/1.1 200 OK
< Content-Type: text/html; charset=UTF-8
< Server: TornadoServer/2.4.1
< Cache-Control: max-age=36000, must-revalidate
< Expires: Tue, 23 Apr 2013 20:18:12 GMT
< Content-Length: 13
< Accept-Ranges: bytes
< Date: Tue, 23 Apr 2013 10:18:28 GMT
< X-Varnish: 1434600184 1434599691
< Age: 16
< Via: 1.1 varnish
< Connection: keep-alive
< X-varnish-cache: HIT
< 
pst
  • 1,414
  • 11
  • 22
  • Is there a way in Cloudcontrol to define settings like Richard Hulse proposed to set the settings for static files (perferably not with an htaccess file which will be parsed upon every request to the Apache)? For php requests, I can adjust the headers as needed, but not really for static files... – Shannera Apr 23 '13 at 23:50
  • Cloudcontrol say this in their docs: "To have your requests cached directly in Varnish and speed up the response time through this, ensure you have set correct cache control headers for the request." So you pretty much have to do this in your Apache config. https://www.cloudcontrol.com/dev-center/Platform%20Documentation#performance--caching – Richard Hulse Apr 24 '13 at 06:02
  • You can either set these directives via a .htaccess file or use the PHP buildpacks custom Apache config option on the Pinky stack. See https://github.com/cloudControl/buildpack-php for details and remember to deploy with --stack pinky. – pst Apr 30 '13 at 08:41