Reading PHP session from Varnish Cache

Posted by on Jul 8, 2013 in Environment, Linux, PHP Programming | No Comments

In my previous post I showed how to integrate Varnish Cache with a PHP application. The example can solve various simple problems but it might not be enough for a complex software. A good example is a multilingual application. One URL can have multiple caches. You might also need to know more about a user (is he logged in? has he received a notification? etc) to make some additional caching decisions.

All of that can be handled with a special cookie(s) which will flag different scenarios but in my experience this is a clumsy solution. You will need to think of all possible user journeys and make sure that appropriate cookies are created. Caching is very difficult on it’s own so there is no need to make it even more complicated. Much better approach in my opinion is pulling data directly from a PHP session.

PHP by default stores session in a file. This might be OK with a single server architecture but if you have more than one web server than you need a centralised storage. Independently of your setup much better place for a PHP session is memcached. It will improve access time, scalability and of course – you will be able to access session from Varnish.

Storing session data inside the memcached is very simple to do with PHP.

Edit the php.ini file.

Look for session settings

and change it to

Now restart apache and it’s done.

If you like you can test it with the below code.

It should return something like this:

If it’s all working lets create a simple page which will simulate multilingual support.

The idea is simple. If langues is set PHP will store it in session as “lang” and appropriate content will be displayed.

The challenge for Varnish is to create and return an appropriate cache based on selected language. Language is saved as a serialised string inside the memcached. It’s stored under “memc.sess.key.UNIQUE_KEY” where the UNIQUE_KEY is a value from the PHPSESSID cookie.

To access memcached from Varnish Cache script you have to install VMOD-Memcached. To compile this module you need Varnish source code.

Get the VMOD and all dependencies.

The extension should be copied into your Varnish vmod directory.

The last missing thing is the default.vcl file.

There are few interesting things going on here.

As you probably can guess Varnish will connect to the memcached server on init.

Now look at the bottom of the vcl_recv function.

VCL language doesn’t allow to define new variables although you can reuse the predefined one (like in this example “req.http“). By the end of this block you should have the whole PHP session stored inside req.http._sess.

You can use

to see output of the std.log function.

The most important code happens inside the vcl_hash subroutine.

You can read more about VCL subroutines here but in a nutshell vcl_hash is responsible for building a hash string under which a cache is going to be saved.

By default Varnish is caching per URL and host but we have to extend it by a language name. This is exactly what happens here. A full hash string will look more less like this:

The last thing worth explaining is what happens inside the vcl_fetch.

If there is a cookie attached to a request Varnish will never return cached content. It comes from an assumption that if there is a cookie the page must be dynamic.

The point of this exercise if to handle dynamic content so we walk around this limitation for http://localhost:8080/ requests by unsetting cookies (it happens only in the Varnish scope).

Now you can start Varnish server (don’t forget to type start).

Open two different web browsers, go to http://localhost:8080/ and start changing languages. POST requests are always forwarded to the web server so session value should be updated. For every GET Varnish should return an appropriate content (according to the current language selection) from cache.

It’s little bit tricky to set it up for the first time but the reward is worth it. Making the Varnish Cache aware of user’s status gives much more flexibility and allows to handle more requests directly from cache. That dramatically drops your hosting costs and increases capacity of your server. Give it a go.

Leave a Reply