[4.1] 721448ef0 Update the documentation on grace and keep

PÃ¥l Hermunn Johansen hermunn at varnish-software.com
Thu Sep 13 13:03:12 UTC 2018


commit 721448ef095eaaffbecb0981de6e79fd32360f21
Author: Pål Hermunn Johansen <hermunn at varnish-software.com>
Date:   Thu Jun 7 14:56:24 2018 +0200

    Update the documentation on grace and keep
    
    This is a back port of 7494d6adc9bad382cf267b352c21f5c1069bb14c,
    in which the main point is to clearly recomend using req.grace
    for the most common use case - using different grace time when
    the backend is healthy. To simplify things, the vcl-grace.rst
    file is just copied from master. It should be accurate also for
    the 4.1 branch.

diff --git a/doc/sphinx/users-guide/vcl-grace.rst b/doc/sphinx/users-guide/vcl-grace.rst
index dad7fd0cb..dddfac5f7 100644
--- a/doc/sphinx/users-guide/vcl-grace.rst
+++ b/doc/sphinx/users-guide/vcl-grace.rst
@@ -1,11 +1,15 @@
 .. _users-guide-handling_misbehaving_servers:
 
-Misbehaving servers
+Grace mode and keep
 -------------------
 
-A key feature of Varnish is its ability to shield you from misbehaving
-web- and application servers.
+Sometimes you want Varnish to serve content that is somewhat stale
+instead of waiting for a fresh object from the backend. For example,
+if you run a news site, serving a main page that is a few seconds old
+is not a problem if this gives your site faster load times.
 
+In Varnish this is achieved by using `grace mode`. A related idea
+is `keep`, which is also explained here.
 
 Grace mode
 ~~~~~~~~~~
@@ -19,52 +23,143 @@ If you are serving thousands of hits per second the queue of waiting
 requests can get huge. There are two potential problems - one is a
 thundering herd problem - suddenly releasing a thousand threads to
 serve content might send the load sky high. Secondly - nobody likes to
-wait. To deal with this we can instruct Varnish to keep
-the objects in cache beyond their TTL and to serve the waiting
-requests somewhat stale content.
+wait.
+
+Setting an object's `grace` to a positive value tells Varnish that it
+should serve the object to clients for some time after the TTL has
+expired, while Varnish fetches a new version of the object. The default
+value is controlled by the runtime parameter ``default_grace``.
+
+Keep
+~~~~
 
-So, in order to serve stale content we must first have some content to
-serve. So to make Varnish keep all objects for 2 minutes beyond their
-TTL use the following VCL::
+Setting an object's `keep` tells Varnish that it should keep an object
+in the cache for some additional time. The reasons to set `keep` is to
+use the object to construct a conditional GET backend request (with
+If-Modified-Since: and/or Ìf-None-Match: headers), allowing the
+backend to reply with a 304 Not Modified response, which may be more
+efficient on the backend and saves re-transmitting the unchanged body.
+
+The values are additive, so if grace is 10 seconds and keep is 1 minute,
+then objects will survive in cache for 70 seconds after the TTL has
+expired.
+
+Setting grace and keep
+~~~~~~~~~~~~~~~~~~~~~~
+
+We can use VCL to make Varnish keep all objects for 10 minutes beyond
+their TTL with a grace period of 2 minutes::
 
   sub vcl_backend_response {
-    set beresp.grace = 2m;
+       set beresp.grace = 2m;
+       set beresp.keep = 8m;
   }
 
-Now Varnish will be allowed to serve objects that are up to two
-minutes out of date. When it does it will also schedule a refresh of
-the object. This will happen asynchronously and the moment the new
-object is in it will replace the one we've already got.
+The effect of grace and keep
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For most users setting the default grace and/or a suitable grace for
+each object is enough. The default VCL will do the right thing and
+behave as described above. However, if you want to customize how
+varnish behaves, then you should know some of the details on how this
+works.
+
+When ``sub vcl_recv`` ends with ``return (lookup)`` (which is the
+default behavior), Varnish will look for a matching object in its
+cache. Then, if it only found an object whose TTL has run out, Varnish
+will consider the following:
+
+* Is there already an ongoing backend request for the object?
+* Is the object within the `grace period`?
+
+Then, Varnish reacts using the following rules:
+
+* If the `grace period` has run out and there is no ongoing backend
+  request, then ``sub vcl_miss`` is called immediately, and the object
+  will be used as a 304 candidate.
+* If the `grace period` has run out and there is an ongoing backend
+  request, then the request will wait until the backend request
+  finishes.
+* If there is no backend request for the object, one is scheduled.
+* Assuming the object will be delivered, ``sub vcl_hit`` is called
+  immediately.
+
+Note that the backend fetch happens asynchronously, and the moment the
+new object is in it will replace the one we've already got.
+
+If you do not define your own ``sub vcl_hit``, then the default one is
+used. It looks like this::
+
+  sub vcl_hit {
+       if (obj.ttl >= 0s) {
+            // A pure unadulterated hit, deliver it
+            return (deliver);
+       }
+       if (obj.ttl + obj.grace > 0s) {
+            // Object is in grace, deliver it
+            // Automatically triggers a background fetch
+            return (deliver);
+       }
+       // fetch & deliver once we get the result
+       return (miss);
+  }
 
-You can influence how this logic works by adding code in vcl_hit. The
-default looks like this::
+The effect of the built-in VCL is in fact equivalent to the following::
 
   sub vcl_hit {
-     if (obj.ttl >= 0s) {
-         // A pure unadultered hit, deliver it
-         return (deliver);
-     }
-     if (obj.ttl + obj.grace > 0s) {
-         // Object is in grace, deliver it
-         // Automatically triggers a background fetch
-         return (deliver);
-     }
-     // fetch & deliver once we get the result
-     return (fetch);
+       return (deliver);
   }
 
-The grace logic is pretty obvious here. If you have enabled
-:ref:`users-guide-advanced_backend_servers-health` you can check if
-the backend is sick and only serve graced object then. Replace the
-second if-clause with something like this::
+This is because ``obj.ttl + obj.grace > 0s`` always will evaluate to
+true. However, the the VCL is as it is to show users how to
+differentiate between a pure hit and a `grace` hit. With the next
+major version of Varnish, the default VCL is planned to change to the
+latter, shorter version.
+
+Misbehaving servers
+~~~~~~~~~~~~~~~~~~~
+
+A key feature of Varnish is its ability to shield you from misbehaving
+web- and application servers.
+
+If you have enabled :ref:`users-guide-advanced_backend_servers-health`
+you can check if the backend is sick and modify the behavior when it
+comes to grace. This can done in the following way::
+
+  sub vcl_backend_response {
+       set beresp.grace = 24h;
+       // no keep - the grace should be enough for 304 candidates
+  }
+
+  sub vcl_recv {
+       if (std.healthy(req.backend_hint)) {
+            // change the behavior for healthy backends: Cap grace to 10s
+            set req.grace = 10s;
+       }
+  }
+
+In the example above, the special variable ``req.grace`` is set.  The
+effect is that, when the backend is healthy, objects with grace above
+10 seconds will have an `effective` grace of 10 seconds.  When the
+backend is sick, the default VCL kicks in, and the long grace is used.
+
+Additionally, you might want to stop cache insertion when a backend fetch
+returns an ``5xx`` error::
+
+  sub vcl_backend_response {
+       if (beresp.status >= 500 && bereq.is_bgfetch) {
+            return (abandon);
+       }
+  }
 
-   if (!std.healthy(req.backend_hint) && (obj.ttl + obj.grace > 0s)) {
-         return (deliver);
-   } else {
-         return (fetch);
-   }
+Summary
+~~~~~~~
 
-So, to sum up, grace mode solves two problems:
- * it serves stale content to avoid request pile-up.
- * it serves stale content if you allow it.
+Grace mode allows Varnish to deliver slightly stale content to clients
+while getting a fresh version from the backend. The result is faster
+load times at lower cost.
 
+It is possible to limit the grace during lookup by setting
+``req.grace`` and then change the behavior when it comes to
+grace. Often this is done to change the `effective` grace depending on
+the health of the backend.


More information about the varnish-commit mailing list