4

I'm new to Varnish Cache and have a question I hope I can get some help with.

I have a very simple and basic setup but it's not working as I understand it should for some reason.

It's related to Varnish not caching PHP pages that are using cookies.

Here is my setup:

1) For my default.vcl I have a simple backend

backend default {
.host = "127.0.0.1";
.port = "80";
}

2) I have a simple PHP file that has only these two line:

session_start();
echo time();

3) When I call this page it correctly does not cache as I have not added in the required vcl rules

4)

So as per my understanding of the documentation I add in these two rules

sub vcl_recv {
unset req.http.Cookie;
return (lookup);
}

sub vcl_fetch {
unset beresp.http.Set-Cookie;
return(deliver);
}

5) The PHP page still will not cache. I can see the Set-Cookie header has been removed as I'm using FireBug in FireFox.

It's only if I add this to sub vcl_fetch that the PHP will cache:

set beresp.ttl = 24h;

My question is is this correct?

I didn't think I would need to alter the ttl of the backend response. I thought just unsetting cookies in and out would force PHP w/ session to cache.

My complete default vcl is:

backend default {
.host = "127.0.0.1";
.port = "80";
}

sub vcl_recv {
unset req.http.Cookie;
return (lookup);
}

sub vcl_fetch {
unset beresp.http.Set-Cookie;
set beresp.ttl = 24h;
return(deliver);
}

My start up command is:

varnishd -f /etc/varnish/default.vcl -s malloc,128M -T 127.0.0.1:2000 -a 0.0.0.0:8080

The URL I am calling is:

http://vbox.local:8080/varnish-tests/index.php

My index.php file has only:

<?php 
session_start();
echo time();

I would like to ask the community if this looks correct or if I am wrong. Essentially I'm just unsure why I had to add the beresp.ttl = 24h to finally have the page cache in varnish.

I thought I would not need this.

Any advise much appreciated.

Thank you!

Kind regards.

Charles
  • 50,943
  • 13
  • 104
  • 142
Jacob
  • 41
  • 1
  • 1
  • 3
  • This matches my experience -- I've set ttls for everything I want varnish to cache in my VCL. How long would you expect varnish to cache something if you don't give it a ttl? – Frank Farmer Mar 29 '11 at 02:06
  • Hey Frank. Your comment makes perfect sense. I was just unsure as I didn't notice anything in the docs about setting the beresp.ttl related to caching cookies. Maybe I mist that in the docs. I spent over 30mins scratching my head until I 'figured' it out. Thanks again. – Jacob Mar 29 '11 at 02:10
  • Something to watch for when caching PHP responses that deal with sessions: PHP will *by default* [send anti-caching headers](http://us2.php.net/manual/en/function.session-cache-limiter.php). If Varnish is obeying these headers, you may have difficulties down the line if you're expecting specific caching behavior (once you solve your current problem, which is entirely unrelated). – Charles Mar 29 '11 at 02:14
  • See also http://stackoverflow.com/questions/9009966/how-to-set-varnish-cache-control-headers – here Feb 21 '15 at 01:25

5 Answers5

5

Varnish will obey the caching headers on the response. PHP will send cache-control headers NOT to cache the response by deafult

Cache-Control:no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma:no-cache

You need to disable those headers otherwise Varnish will obey and thus not cache the page. To turn them off simply call session_cache_limiter() with an empty string

session_cache_limiter('');
header("Cache-Control: public, s-maxage=60");
session_start();

You can then add a header to set the cache-control to public. Using the three lines above will enable caching.

Joshua Ostrom
  • 51
  • 1
  • 2
4

As ZoFreX said, that's probably because of your Cache-Control or Expires header.

Also note that this rule is a little dangerous :

sub vcl_recv {
    unset req.http.Cookie;
    return (lookup);
}
sub vcl_fetch {
    unset beresp.http.Set-Cookie;
    return(deliver);
}

If your server sends cookies, that's probably because you need them, at least for sessions. That kind of rule will totally disable session management of you application server.

Depending on why you use sessions, you can not cache every part of your content (eg : user specific content).

1

You should look very carefully at the headers PHP is sending to Varnish (e.g. by accessing your server directly rather than through varnishd). If the headers say that the content can't be cached, it won't be. If they don't say that it can be cached, it won't be - and I suspect this is why Varnish is only caching if you manually set the ttl, as the headers don't have "expires" or "max-age".

ZoFreX
  • 8,812
  • 5
  • 31
  • 51
1

The easiest way to get a response cached by varnish would be to add the cache-control header.

php:

header('Cache-Control: public, s-maxage=60');

would tell varnish to cache the response for 60 seconds.

moritz
  • 11
  • 2
0

I was having exactly the same problem. When you do a session_start, it appears that PHP notices that the page is potentially dynamic and helpfully resets the cache control headers to this:

Cache-Control:no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma:no-cache

The default configuration of Varnish obeys these caching directives sent by apache/php, meaning it won't cache these pages. I'm not 100% sure it's possible to override the default configuration either, only to extend it.

The workaround that I've been using is to re-set the Cache-Control headers, but note that this has to be done after the session_start has changed them. I've not tested to see if it also needs to be after the session_write_close also, but better safe than sorry.

Li1t
  • 622
  • 6
  • 16