Provided by: varnish_7.5.0-3_amd64 bug

NAME

       vmod_directors - Varnish Directors Module

SYNOPSIS

          import directors [as name] [from "path"]

          new xround_robin = directors.round_robin()

              VOID xround_robin.add_backend(BACKEND)

              VOID xround_robin.remove_backend(BACKEND)

              BACKEND xround_robin.backend()

          new xfallback = directors.fallback(BOOL sticky)

              VOID xfallback.add_backend(BACKEND)

              VOID xfallback.remove_backend(BACKEND)

              BACKEND xfallback.backend()

          new xrandom = directors.random()

              VOID xrandom.add_backend(BACKEND, REAL)

              VOID xrandom.remove_backend(BACKEND)

              BACKEND xrandom.backend()

          new xhash = directors.hash()

              VOID xhash.add_backend(BACKEND, REAL weight)

              VOID xhash.remove_backend(BACKEND)

              BACKEND xhash.backend(STRING)

          new xshard = directors.shard()

              VOID xshard.set_warmup(REAL probability)

              VOID xshard.set_rampup(DURATION duration)

              VOID xshard.associate(BLOB param)

              BOOL xshard.add_backend(BACKEND backend, [STRING ident], [DURATION rampup], [REAL weight])

              BOOL xshard.remove_backend([BACKEND backend], [STRING ident])

              BOOL xshard.clear()

              BOOL xshard.reconfigure(INT replicas)

              INT xshard.key(STRING)

              BACKEND xshard.backend([ENUM by], [INT key], [BLOB key_blob], [INT alt], [REAL warmup], [BOOL rampup], [ENUM healthy], [BLOB param], [ENUM resolve])

              VOID xshard.debug(INT)

          new xshard_param = directors.shard_param()

              VOID xshard_param.clear()

              VOID xshard_param.set([ENUM by], [INT key], [BLOB key_blob], [INT alt], [REAL warmup], [BOOL rampup], [ENUM healthy])

              STRING xshard_param.get_by()

              INT xshard_param.get_key()

              INT xshard_param.get_alt()

              REAL xshard_param.get_warmup()

              BOOL xshard_param.get_rampup()

              STRING xshard_param.get_healthy()

              BLOB xshard_param.use()

          BACKEND lookup(STRING)

DESCRIPTION

       vmod_directors enables backend load balancing in Varnish.

       The  module implements load balancing techniques, and also serves as an example on how one
       could extend the load balancing capabilities of Varnish.

       To enable load balancing you must import this vmod (directors).

       Then you define your backends. Once you have the backends declared you can add them  to  a
       director.  This happens in executed VCL code. If you want to emulate the previous behavior
       of Varnish 3.0 you can just initialize the directors in vcl_init{}, like this:

          sub vcl_init {
              new vdir = directors.round_robin();
              vdir.add_backend(backend1);
              vdir.add_backend(backend2);
          }

       As you can see there is nothing keeping you from manipulating the directors  elsewhere  in
       VCL. So, you could have VCL code that would add more backends to a director when a certain
       URL is called.

       Note that directors can use other directors as backends.

   new xround_robin = directors.round_robin()
       Create a round robin director.

       This director will pick backends in a round robin fashion.

       Example:

          new vdir = directors.round_robin();

   VOID xround_robin.add_backend(BACKEND)
       Add a backend to the round-robin director.

       Example:

          vdir.add_backend(backend1);

   VOID xround_robin.remove_backend(BACKEND)
       Remove a backend from the round-robin director.

       Example:

          vdir.remove_backend(backend1);

   BACKEND xround_robin.backend()
       Pick a backend from the director.

       Example:

          set req.backend_hint = vdir.backend();

   new xfallback = directors.fallback(BOOL sticky=0)
       Create a fallback director.

       A fallback director will try each of the added backends in turn, and return the first  one
       that is healthy.

       If  sticky  is  set  to  true, the director will keep using the healthy backend, even if a
       higher-priority backend becomes available. Once the whole backend list is exhausted, it'll
       start over at the beginning.

       Example:

          new vdir = directors.fallback();

   VOID xfallback.add_backend(BACKEND)
       Add a backend to the director.

       Note that the order in which this is done matters for the fallback director.

       Example:

          vdir.add_backend(backend1);

   VOID xfallback.remove_backend(BACKEND)
       Remove a backend from the director.

       Example:

          vdir.remove_backend(backend1);

   BACKEND xfallback.backend()
       Pick a backend from the director.

       Example:

          set req.backend_hint = vdir.backend();

   new xrandom = directors.random()
       Create a random backend director.

       The random director distributes load over the backends using a weighted random probability
       distribution.

       The "testable" random generator in varnishd is used, which enables deterministic tests  to
       be run (See: d00004.vtc).

       Example:

          new vdir = directors.random();

   VOID xrandom.add_backend(BACKEND, REAL)
       Add a backend to the director with a given weight.

       Each backend will receive approximately 100 * (weight / (sum(all_added_weights))) per cent
       of the traffic sent to this director.

       Example:

          # 2/3 to backend1, 1/3 to backend2.
          vdir.add_backend(backend1, 10.0);
          vdir.add_backend(backend2, 5.0);

   VOID xrandom.remove_backend(BACKEND)
       Remove a backend from the director.

       Example:

          vdir.remove_backend(backend1);

   BACKEND xrandom.backend()
       Pick a backend from the director.

       Example:

          set req.backend_hint = vdir.backend();

   new xhash = directors.hash()
       Create a hashing backend director.

       The director chooses the backend server by computing a hash/digest of the string given  to
       xhash.backend().

       Commonly used with client.ip or a session cookie to get sticky sessions.

       Example:

          new vdir = directors.hash();

   VOID xhash.add_backend(BACKEND, REAL weight=1.0)
       Add a backend to the director with a certain weight.

       Weight  is used as in the random director. Recommended and default value is 1.0 unless you
       have special needs.

       Example:

          vdir.add_backend(normal_backend);
          vdir.add_backend(larger_backend, 1.5);

   VOID xhash.remove_backend(BACKEND)
       Remove a backend from the director.

       Example::
              vdir.remove_backend(larger_backend);

   BACKEND xhash.backend(STRING)
       Pick a backend from the hash director.

       Use the string or list of strings provided to pick the backend.

       Example::
              # pick a backend based on the cookie header from the client set req.backend_hint  =
              vdir.backend(req.http.cookie);

   new xshard = directors.shard()
       Create a shard director.

   Introduction
       The  shard  director  selects backends by a key, which can be provided directly or derived
       from strings. For the same key, the shard director will always return  the  same  backend,
       unless  the backend configuration or health state changes. Conversely, for differing keys,
       the shard director will likely choose different backends. In  the  default  configuration,
       unhealthy backends are not selected.

       The  shard  director resembles the hash director, but its main advantage is that, when the
       backend configuration or health states change, the association of keys to backends remains
       as stable as possible.

       In  addition,  the  rampup  and warmup features can help to further improve user-perceived
       response times.

   Sharding
       This basic technique allows for numerous applications like optimizing backend server cache
       efficiency,  Varnish  clustering  or  persisting  sessions  to servers without keeping any
       state, and, in particular, without the need  to  synchronize  state  between  nodes  of  a
       cluster of Varnish servers:

       • Many  applications use caches for data objects, so, in a cluster of application servers,
         requesting similar objects from the same server may help to optimize efficiency of  such
         caches.

         For  example,  sharding  by  URL  or  some  id  component  of  the url has been shown to
         drastically improve the efficiency of many content management systems.

       • As special case of  the  previous  example,  in  clusters  of  Varnish  servers  without
         additional  request  distribution  logic, each cache will need store all hot objects, so
         the effective cache size is approximately the smallest cache size of any server  in  the
         cluster.

         Sharding  allows  to  segregate objects within the cluster such that each object is only
         cached on one of the servers (or on one primary and one backup, on a  primary  for  long
         and  others  for short etc...). Effectively, this will lead to a cache size in the order
         of the sum of  all  individual  caches,  with  the  potential  to  drastically  increase
         efficiency (scales by the number of servers).

       • Another  application  is  to  implement  persistence  of backend requests, such that all
         requests sharing a certain criterion (such as an IP address or session ID) get forwarded
         to the same backend server.

       When  used  with  clusters  of  varnish  servers,  the  shard  director will, if otherwise
       configured equally, make the same decision  on  all  servers.  In  other  words,  requests
       sharing  a  common  criterion used as the shard key will be balanced onto the same backend
       server(s) no matter which Varnish server handles the request.

       The drawbacks are:

       • the distribution of requests  depends  on  the  number  of  requests  per  key  and  the
         uniformity of the distribution of key values. In short, while this technique may lead to
         much better efficiency overall, it may  also  lead  to  less  good  load  balancing  for
         specific cases.

       • When a backend server becomes unavailable, every persistence technique has to reselect a
         new backend server, but this technique will also switch back  to  the  preferred  server
         once it becomes healthy again, so when used for persistence, it is generally less stable
         compared to stateful techniques (which would continue to use a selected  server  for  as
         long as possible (or dictated by a TTL)).

   Method
       When  xshard.reconfigure()  is  called  explicitly  (or  implicitly at the end of any task
       containing reconfigurations like xshard.add_backend()), a consistent hashing circular data
       structure  gets  built  from the last 32 bits of SHA256 hash values of <ident><n> (default
       ident being the backend name) for each backend and for a running number n from  1  to  the
       replicas  argument to xshard.reconfigure(). Hashing creates the seemingly random order for
       placement of backends on the consistent hashing ring. When xshard.add_backend() was called
       with  a  weight  argument,  replicas  is  scaled by that weight to add proportionally more
       copies of the that backend on the ring.

       When xshard.backend() is called, a load balancing key gets generated unless provided.  The
       smallest  hash  value  in  the  circle is looked up that is larger than the key (searching
       clockwise and wrapping around as necessary). The  backend  for  this  hash  value  is  the
       preferred backend for the given key.

       If a healthy backend is requested, the search is continued linearly on the ring as long as
       backends found are unhealthy or all  backends  have  been  checked.  The  order  of  these
       "alternative  backends"  on  the  ring is likely to differ for different keys. Alternative
       backends can also be selected explicitly.

       On consistent hashing see:

       • http://www8.org/w8-papers/2a-webserver/caching/paper2.htmlhttp://www.audioscrobbler.net/development/ketama/

       • svn://svn.audioscrobbler.net/misc/ketama

       • http://en.wikipedia.org/wiki/Consistent_hashing

   Error Reporting
       Failing methods should report errors to VSL with the Error tag, so  when  configuring  the
       shard director, you are advised to check:

          varnishlog -I Error:^vmod_directors.shard

       Additional information may be provided as Notices, which can be checked using
          varnishlog -I Notice:^vmod_directors.shard

   VOID xshard.set_warmup(REAL probability=0.0)
       Set  the  default  warmup  probability.  See  the warmup parameter of xshard.backend(). If
       probability is 0.0 (default), warmup is disabled.

   VOID xshard.set_rampup(DURATION duration=0)
       Set the default rampup duration. See rampup parameter of xshard.backend(). If duration  is
       0 (default), rampup is disabled.

   VOID xshard.associate(BLOB param=0)
       Associate a default directors.shard_param() object or clear an association.

       The  value  of  the  param  argument  must  be a call to the xshard_param.use() method. No
       argument clears the association.

       The  association  can  be  changed  per  backend  request  using  the  param  argument  of
       xshard.backend().

   BOOL xshard.add_backend(BACKEND backend, [STRING ident], [DURATION rampup], [REAL weight])
          BOOL xshard.add_backend(
                BACKEND backend,
                [STRING ident],
                [DURATION rampup],
                [REAL weight]
          )

       Add a backend backend to the director.

       ident:  Optionally specify an identification string for this backend, which will be hashed
       by xshard.reconfigure() to construct  the  consistent  hashing  ring.  The  identification
       string defaults to the backend name.

       ident allows to add multiple instances of the same backend.

       rampup:  Optionally  specify  a  specific  rampup  time  for  this backend. Otherwise, the
       per-director rampup time is used (see xshard.set_rampup()).

       weight: Optionally specify a weight to scale the xshard.reconfigure() replicas  parameter.
       weight  is  limited  to  at  least 1. Values above 10 probably do not make much sense. The
       effect of weight is also capped such that the total number of  replicas  does  not  exceed
       UINT32_MAX.

   BOOL xshard.remove_backend([BACKEND backend], [STRING ident])
          BOOL xshard.remove_backend(
                [BACKEND backend=0],
                [STRING ident=0]
          )

       Remove  backend(s)  from  the  director.  Either backend or ident must be specified. ident
       removes a specific instance. If backend is given without  ident,  all  instances  of  this
       backend are removed.

   BOOL xshard.clear()
       Remove all backends from the director.

   BOOL xshard.reconfigure(INT replicas=67)
       Explicitly  reconfigure  the  consistent hashing ring to reflect backend changes to become
       effective immediately.

       If this method is not called explicitly, reconfiguration happens at the end of the current
       task (after vcl_init {} or when the current client or backend task is finished).

   INT xshard.key(STRING)
       Convenience  method  to  generate  a  sharding  key  for  use with the key argument to the
       xshard.backend() method by hashing the given string with SHA256.

       To generate sharding keys using other hashes, use a custom vmod like vmod blobdigest  with
       the key_blob argument of the xshard.backend() method.

   BACKEND  xshard.backend([ENUM by], [INT key], [BLOB key_blob], [INT alt], [REAL warmup], [BOOL
       rampup], [ENUM healthy], [BLOB param], [ENUM resolve])
          BACKEND xshard.backend(
                [ENUM {HASH, URL, KEY, BLOB} by=HASH],
                [INT key],
                [BLOB key_blob],
                [INT alt=0],
                [REAL warmup=-1],
                [BOOL rampup=1],
                [ENUM {CHOSEN, IGNORE, ALL} healthy=CHOSEN],
                [BLOB param],
                [ENUM {NOW, LAZY} resolve]
          )

       Lookup a backend on the consistent hashing ring.

       This documentation uses the notion of an order of backends for  a  particular  shard  key.
       This  order  is deterministic but seemingly random as determined by the consistent hashing
       algorithm and is likely to differ for different keys, depending on the number of  backends
       and the number of replicas. In particular, the backend order referred to here is _not_ the
       order given when backends are added.

       • by how to determine the sharding key

         • HASH:

           • when called in backend context and in vcl_pipe {}: Use the varnish hash value as set
             by vcl_hash{}

           • when called in client context other than vcl_pipe {}: hash req.urlURL: hash req.url / bereq.url

         • KEY: use the key argument

         • BLOB: use the key_blob argument

       • key lookup key with by=KEY

         the xshard.key() method may come handy to generate a sharding key from custom strings.

       • key_blob lookup key with by=BLOB

         Currently,  this  uses  the first 4 bytes from the given blob in network byte order (big
         endian), left-padded with zeros for blobs smaller than 4 bytes.

       • alt alternative backend selection

         Select the alt-th alternative backend for the given key.

         This is particularly useful for retries / restarts due to  backend  errors:  By  setting
         alt=req.restarts or alt=bereq.retries with healthy=ALL, another server gets selected.

         The rampup and warmup features are only active for alt==0rampup slow start for servers which just went healthy

         If  alt==0  and  the  chosen  backend  is  in  its  rampup  period,  with  a probability
         proportional to the fraction of time since the  backup  became  healthy  to  the  rampup
         period, return the next alternative backend, unless this is also in its rampup period.

         The  default rampup interval can be set per shard director using the xshard.set_rampup()
         method or specifically per backend with the xshard.add_backend() method.

       • warmup probabilistic alternative server selection

         possible values: -1, 0..1

         -1: use the warmup probability from the director definition

         Only used for alt==0: Sets the ratio of requests (0.0 to 1.0)  that  goes  to  the  next
         alternate backend to warm it up when the preferred backend is healthy. Not active if any
         of the preferred or alternative backend are in rampup.

         warmup=0.5 is a convenient way to spread the load for each key over two  backends  under
         normal operating conditions.

       • healthy

         • CHOSEN: Return a healthy backend if possible.

           For alt==0, return the first healthy backend or none.

           For  alt  >  0,  ignore  the  health state of backends skipped for alternative backend
           selection, then return the next healthy backend. If this does not  exist,  return  the
           last healthy backend of those skipped or none.

         • IGNORE: Completely ignore backend health state

           Just return the first or alt-th alternative backend, ignoring health state, rampup and
           warmup.

         • ALL: Check health state also for alternative backend selection

           For alt > 0, return the alt-th alternative backend of  all  those  healthy,  the  last
           healthy backend found or none.

       • resolve

         default: LAZY in vcl_init{}, NOW otherwise

         • NOW: look up a backend and return it.

           Can not be used in vcl_init{}.

         • LAZY: return an instance of this director for later backend resolution.

           LAZY  mode  is  required  for  referencing  shard  director  instances, for example as
           backends for other directors (director layering).

           In vcl_init{} and on the client side, LAZY  mode  can  not  be  used  with  any  other
           argument.

           On  the  backend  side  and in vcl_pipe {}, parameters from arguments or an associated
           parameter set affect the shard director instance for the backend request  irrespective
           of where it is referenced.

       • param

         Use  or associate a parameter set. The value of the param argument must be a call to the
         xshard_param.use() method.

         default: as set by xshard.associate() or unset.

         • for resolve=NOW take parameter defaults from the directors.shard_param() parameter set

         • for resolve=LAZY associate the directors.shard_param() parameter set for this  backend
           request

           Implementation notes for use of parameter sets with resolve=LAZY:

           • A  param argument remains associated and any changes to the associated parameter set
             affect the sharding decision once the director resolves to an actual backend.

           • If other parameter arguments are also given, they have preference and are kept  even
             if  the parameter set given by the param argument is subsequently changed within the
             same backend request.

           • Each call to xshard.backend() overrides any previous call.

   VOID xshard.debug(INT)
       intentionally undocumented

   new xshard_param = directors.shard_param()
       Create a shard parameter set.

       A parameter set allows for re-use of xshard.backend() arguments across many shard director
       instances  and  simplifies  advanced use cases (e.g. shard director with custom parameters
       layered below other directors).

       Parameter sets have two scopes:

       • per-VCL scope defined in vcl_init{}

       • per backend request scope

       The per-VCL scope defines defaults for the per backend scope. Any changes to  a  parameter
       set in backend context and in vcl_pipe {} only affect the respective backend request.

       Parameter sets can not be used in client context except for vcl_pipe {}.

       The  following  example  is a typical use case: A parameter set is associated with several
       directors. Director choice happens on the client side and parameters are  changed  on  the
       backend side to implement retries on alternative backends:

          sub vcl_init {
            new shard_param = directors.shard_param();

            new dir_A = directors.shard();
            dir_A.add_backend(...);
            dir_A.reconfigure();
            dir_A.associate(shard_param.use()); # <-- !

            new dir_B = directors.shard();
            dir_B.add_backend(...);
            dir_B.reconfigure();
            dir_B.associate(shard_param.use()); # <-- !
          }

          sub vcl_recv {
            if (...) {
              set req.backend_hint = dir_A.backend(resolve=LAZY);
            } else {
              set req.backend_hint = dir_B.backend(resolve=LAZY);
            }
          }

          sub vcl_backend_fetch {
            # changes dir_A and dir_B behaviour
            shard_param.set(alt=bereq.retries, by=URL);
          }

   VOID xshard_param.clear()
       Reset the parameter set to default values as documented for xshard.backend().

       • in vcl_init{}, resets the parameter set default for this VCL in

       • backend context and in vcl_pipe {}, resets the parameter set for this backend request to
         the VCL defaults

       Restricted to: vcl_pipe, backend, housekeeping.

   VOID xshard_param.set([ENUM by], [INT key], [BLOB key_blob], [INT alt], [REAL  warmup],  [BOOL
       rampup], [ENUM healthy])
          VOID xshard_param.set(
                [ENUM {HASH, URL, KEY, BLOB} by],
                [INT key],
                [BLOB key_blob],
                [INT alt],
                [REAL warmup],
                [BOOL rampup],
                [ENUM {CHOSEN, IGNORE, ALL} healthy]
          )

       Change the given parameters of a parameter set as documented for xshard.backend().

       • in vcl_init{}, changes the parameter set default for this VCL

       • in  backend  context  and  in  vcl_pipe  {},  changes the parameter set for this backend
         request, keeping the defaults set for this VCL for unspecified arguments.

       Restricted to: vcl_pipe, backend, housekeeping.

   STRING xshard_param.get_by()
       Get a string representation of the by enum argument which denotes  how  a  shard  director
       using this parameter object would derive the shard key. See xshard.backend().

   INT xshard_param.get_key()
       Get  the  key  which  a  shard  director  using  this  parameter  object  would  use.  See
       xshard.backend().

   INT xshard_param.get_alt()
       Get the alt parameter which a shard director using this parameter object  would  use.  See
       xshard.backend().

   REAL xshard_param.get_warmup()
       Get the warmup parameter which a shard director using this parameter object would use. See
       xshard.backend().

   BOOL xshard_param.get_rampup()
       Get the rampup parameter which a shard director using this parameter object would use. See
       xshard.backend().

   STRING xshard_param.get_healthy()
       Get a string representation of the healthy enum argument which a shard director using this
       parameter object would use. See xshard.backend().

   BLOB xshard_param.use()
       For use with the param argument of xshard.backend() to associate this shard parameter  set
       with a shard director.

       Restricted to: vcl_pipe, backend, housekeeping.

   BACKEND lookup(STRING)
       Lookup a backend by its name.

       Restricted to: housekeeping.

ACKNOWLEDGEMENTS

       Development  of  a previous version of the shard director was partly sponsored by Deutsche
       Telekom AG - Products & Innovation.

       Development of a previous version of the shard director was partly sponsored by BILD  GmbH
       & Co KG.

COPYRIGHT

          This document is licensed under the same licence as Varnish
          itself. See LICENCE for details.

          SPDX-License-Identifier: BSD-2-Clause

          Copyright (c) 2013-2015 Varnish Software AS
          Copyright 2009-2020 UPLEX - Nils Goroll Systemoptimierung
          All rights reserved.

          Authors: Poul-Henning Kamp <phk@FreeBSD.org>
                   Julian Wiesener <jw@uplex.de>
                   Nils Goroll <slink@uplex.de>
                   Geoffrey Simmons <geoff@uplex.de>

          SPDX-License-Identifier: BSD-2-Clause

          Redistribution and use in source and binary forms, with or without
          modification, are permitted provided that the following conditions
          are met:
          1. Redistributions of source code must retain the above copyright
             notice, this list of conditions and the following disclaimer.
          2. Redistributions in binary form must reproduce the above copyright
             notice, this list of conditions and the following disclaimer in the
             documentation and/or other materials provided with the distribution.

          THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
          ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
          IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
          ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
          FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
          DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
          OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
          HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
          LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
          OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
          SUCH DAMAGE.

                                                                                VMOD_DIRECTORS(3)