Skip to main content

Upgrading to Drupal 8 with Varnish, Time to Upgrade your Mental Model as well

I've been using Varnish with my Drupal sites for quite a long while (as a replacement to the Drupal anonymous page cache). I've just started using Drupal 8 and naturally want to use Varnish for those sites as well. If you've been using Varnish with Drupal in the past, you've already wrapped your head around the complexities of front-end anonymous page caching, presumably, and you know that the varnish module was responsible for translating/passing the Drupal page cache-clear requests to Varnish - explicitly from the performance page, but also as a side effect of editing nodes, etc.

But if you've been paying attention to Drupal 8, you'll know that it's much smarter about cache clearing. Rather than relying on explicit calls to clear specific or all cached pages, it uses 'cache tags' which require another layer of abstraction in your brain to understand.

Specifically, the previous mechanism in Drupal 7 and earlier was by design 'conservative' in the sense that many changes to the site caused way more cache clearing than was necessary, just because it had to be sure. So for example, if you edited a node, it would clear the whole site's page cache, because it had no idea which urls that piece of content might show up on (e.g. you might have a 'New content' block on every page that changes with any node edit).

The cache-tags solve this in a 'declarative' way by explicitly declaring dependencies when each page is built by Drupal. So if a page is built and it uses node 5 somewhere in building it, then there's a cache tag attached to the page that says 'node-5'.

With this in place, you can now see that Drupal can be much more clever about clearing caches - e.g. if you edit node 5, you can just clear the pages that have the node-5 cache-tag on it.

Nice idea, and of course, since cache-invalidation is one of those hard things in computing, it's not as easy as it sounds.

But if you're still game, here are a few useful bits I gleaned along the way:

1. The old Drupal varnish module communicated with varnish using the varnish admin port. The New and Better way to talk to varnish is via port 80, using special http methods PURGE and BAN. This means your vcl needs a bit of work (to restrict access, and to do the right thing when receiving these requests, recipe below). You really need to understand the difference between PURGE and BAN - it's the BAN that you're going to use, and the names change in the most recent varnish versions.

2. There is no varnish module for D8 (yet?). There is a 'purge' module and a 'varnish purge' module that together can clear the Varnish page cache correctly. And they use the varnish BAN method, not the PURGE method. Got it?

3. The basic idea is that those cache-tags get attached as http headers to the page, which is then passed to Varnish to deliver. Along the way, Varnish caches the page and then strips off the header before sending it off. So now all those cache tags known by Varnish. The cache tags don't get attached as http headers by default, that needs to be explicitly configured.

4. Now the cache clear request from Drupal gets converted into a BAN request with the appropriate headers, using the purge + varnish_purge modules as per the official recipe or here's a more useful, detailed recipe. But both are confused about the name the cache tag http header, which is currently set to just Cache-Tags (not Purge-Cache-Tags, not X-Cache-Tags).

6. None of that did anything for me and I thought I was still confused (well, yes, I was) until I discovered that the purge module queues up the request but doesn't actually do anything with those requests by default. In the Purge queue, you can actually look in the database of requests, where I saw all my purge requests (yeah, which should get translated to Varnish BAN requests). You can configure how those get triggered, the simple one is as a cron, but that's not going to be super great for many sites. I haven't figured out what the right mechanism might be, but I guess a custom cron every 5 minutes that only does this one cron task would be okay.

So, a lot of new things to learn.

Popular posts from this blog

Orchestrating Drupal + CiviCRM containers into a working site: describing the challenge

In my previous posts, I've provided my rationale for making use of Docker and the microservices model for a boutique-sized Drupal + CiviCRM hosting service. I've also described how to build and maintain images that could be used for the web server (micro) service part of such a service.

The other essential microservice for a Drupal + CiviCRM website is a database, and fortunately, that's reasonably standard. Here's a project that minimally tweaks the canonical Mariadb container by adding some small configuration bits:

That leaves us now with the problem of "orchestration", i.e. how would you launch a collection of such containers that would serve a bunch of Drupal + CiviCRM sites. More interestingly, can we serve them in the real world, over time, in a way that is sustainable? i.e. handle code updates, OS updates, backups, monitoring, etc? Not to mention the various crons that need to run, and how about things like…

Building and maintaining Drupal + CiviCRM application containers

In my previous two posts, I provided some background into why I decided on using containers for a boutique Drupal + CiviCRM hosting platform, and why Docker and its micro-services approach is a good choice for building and maintaining containers.

Although I promised to talk about orchestration, that was getting ahead of the story - first I'm going to look at the challenge of keeping your application containers up-to-date with OS and application-level updates. There's a fair amount of work in that, but the tooling is mature and there is lots of good documentation.

A great place to start is to visit the official Drupal docker hub page. From there, you can pull a working Drupal code container, and it gets re-built frequently with all the OS and Drupal-code updates, so you just refresh your containers whenever you want (i.e. whenever a security release comes out, or more often to stay up-to-date).

A nice thing about that project is that it demonstrates a technique for maintaining …

IATS and CiviCRM

Update, Nov 2009: I've just discovered and fixed a bug I introduced in the 2.2 branch for the IATS plugin. The bug was introduced when i updated the API files from IATS and failed to notice that the legacy method for C$ one-time donations was no longer supported.
If you're using a version greater than or equal to 2.2.7, and are using IATS for C$, non-recurring donations, then you're affected.
To fix it edit the file : CRM/Core/Payment/IATS.php, and remove the line that looks like this:

$canDollar = ($params['currencyID'] == 'CAD'); //define currency type The full fix removes a conditional branch based on that value a little further on, but by removing this line, it'll never actually use that branch. Drop me a line if you have any questions.
Update, May 2009: This post is still getting quite a bit of traffic, which is great. Here are a few important things to note:
The IATS plugin code is in CiviCRM, you don't need to add any code.You do still …