[6.0] ab7b2b184 Update the documentation on grace and keep
Dridi Boukelmoune
dridi.boukelmoune at gmail.com
Thu Aug 16 08:53:17 UTC 2018
commit ab7b2b184c7dcc5ffea4b8ec812de95ec2ead874
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
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.
diff --git a/doc/sphinx/users-guide/vcl-grace.rst b/doc/sphinx/users-guide/vcl-grace.rst
index 8db2a4649..dddfac5f7 100644
--- a/doc/sphinx/users-guide/vcl-grace.rst
+++ b/doc/sphinx/users-guide/vcl-grace.rst
@@ -34,15 +34,11 @@ Keep
~~~~
Setting an object's `keep` tells Varnish that it should keep an object
-in the cache for some additional time. There are two reasons to do this:
-
-* 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.
-* To be able to serve the object when grace has expired but we have a
- problem with getting a fresh object from the backend. This will require
- a change in ``sub vcl_hit``, as described below.
+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
@@ -64,9 +60,9 @@ 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 by changing ``sub vcl_hit``, then you should know some of the
-details on how this works.
+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
@@ -78,13 +74,15 @@ will consider the following:
Then, Varnish reacts using the following rules:
-* If there is no backend request for the object, one is scheduled and
- ``sub vcl_hit`` is called immediately.
-* If there is a backend request going on, but the object is under grace,
- ``sub vcl_hit`` is called immediately.
-* If there is a backend request going on, but the grace has expired,
- processing is halted until the backend request has finished and a
- fresh object is available.
+* 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.
@@ -106,9 +104,17 @@ used. It looks like this::
return (miss);
}
-If you follow the code, you see that Varnish delivers graced objects
-while fetching fresh copies, but if grace has expired the clients have to
-wait until a new copy is available.
+The effect of the built-in VCL is in fact equivalent to the following::
+
+ sub vcl_hit {
+ return (deliver);
+ }
+
+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
~~~~~~~~~~~~~~~~~~~
@@ -118,104 +124,42 @@ 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. There are essentially two ways of doing this. You can
-explicitly deliver kept object (that is not within grace) when you see
-that the backend is sick, or you can explicitly `not` serve an expired
-object when you know that the backend is healthy. The two methods have
-slightly different characteristics, as we shall see.
-
-In both cases we assume that you avoid inserting objects into the cache
-when you get certain errors from the backend, for example by using the
-following::
-
- sub vcl_backend_response {
- if (beresp.status == 503 && bereq.is_bgfetch) {
- return (abandon);
- }
- }
-
-Method 1: When the backend is healthy, use a lower grace value
-==============================================================
-
-Imagine that you have set an object's grace to a high value that you
-wish to use when the backend is sick, for example::
+comes to grace. This can done in the following way::
sub vcl_backend_response {
set beresp.grace = 24h;
- // no keep
+ // no keep - the grace should be enough for 304 candidates
}
-Then you can use the following code as your ``sub vcl_hit``::
-
- if (std.healthy(req.backend_hint)) {
- // change the behavior for health backends: Cap grace to 10s
- if (obj.ttl + obj.grace > 0s && obj.ttl + 10s > 0s) {
- return (deliver);
- } else {
- return (miss);
- }
- }
-
-The effect of this 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.
-
-This method has one potentially serious problem when more than one
-client asks for an object that has expired its TTL. If the second of
-these requests arrives after the effective grace, but before the first
-request has completed, then the second request will be turned into a
-`pass`.
-
-In practice this method works well in most cases, but if you
-experience excessive `pass` behavior, this translates to a reduced
-hit rate and higher load on the backend. When this happens you will
-see the error message `vcl_hit{} returns miss without busy object` in
-the log.
-
-Method 2: When the backend is sick, deliver kept objects
-========================================================
-
-With this method, we assume that we have used `sub backend_response`
-to set `beresp.grace` to a value that is suitable for healthy backends,
-and with a `beresp.keep` that corresponds to the time we want to serve
-the object when the backend is sick. For example::
-
- sub vcl_backend_response {
- set beresp.grace = 10s;
- set beresp.keep = 24h;
+ sub vcl_recv {
+ if (std.healthy(req.backend_hint)) {
+ // change the behavior for healthy backends: Cap grace to 10s
+ set req.grace = 10s;
+ }
}
-The appropriate code for ``vcl_hit`` then becomes::
-
- if (!std.healthy(req.backend_hint) && (obj.ttl + obj.grace + obj.keep > 0s)) {
- return (deliver);
- }
+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.
-Typically you can omit the second part of the if test due to the
-expiry thread deleting objects where `grace + keep` has expired. It is
-possible that the `expiry thread` can be lagging slightly behind, but
-for almost all practical purposes you are probably fine with the
-following::
+Additionally, you might want to stop cache insertion when a backend fetch
+returns an ``5xx`` error::
- if (!std.healthy(req.backend_hint)) {
- return (deliver);
- }
-
-The problem with this solution concerns requests that are waiting for
-a backend fetch to finish. If the backend fetch gets to ``return
-(abandon)``, then all the requests that are waiting will get to ``sub
-vcl_hit`` with an `error object` created by the error handling
-code/VCL. In other words, you risk that some clients will get errors
-instead of the more desirable stale objects.
+ sub vcl_backend_response {
+ if (beresp.status >= 500 && bereq.is_bgfetch) {
+ return (abandon);
+ }
+ }
Summary
~~~~~~~
-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
-with a low cost.
+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 change the behavior when it comes to grace and keep, for
-example by changing the `effective` grace depending on the health of the
-backend, but you have to be careful.
+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