#- # Copyright (c) 2013-2015 Varnish Software AS # All rights reserved. # # Author: Poul-Henning Kamp # # Copyright (c) 2016-2017 GANDI SAS # All rights reserved. # # Author: Emmanuel Hocdet # # 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. $Module unidirectors 3 Varnish Directors Module DESCRIPTION =========== `vmod_unidirectors` enables backend load balancing in Varnish. The module implements a set of load balancing techniques. It's based on vmod_directors. The major change is the unification of directors type and the ability to change the load balancing method dynamically. Dynamic backends is built in with dyndirector, all load balancing method is supported. To enable load balancing you must import this vmod (unidirectors). 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 udir2 = unidirectors.dyndirector(); udir2.leastconn(); udir2.lookup_addr("service1.example.net"); new udir1 = unidirectors.director(); udir1.hash("client-identity"); udir1.add_backend(backendA); udir1.add_backend(backendB); new udir = unidirectors.director(); udir.fallback(); udir.add_backend(udir1.backend()); udir.add_backend(udir2.backend()); } 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. $Object director() Description Create a director. The default load balancing is random. Load balancing method can be changed. Example new udir = unidirectors.director() $Method VOID .round_robin() Description Configure a director as round robin. This director will pick backends in a round robin fashion according to weight. Example udir.round_robin(); $Method VOID .fallback(BOOL sticky=0) Description Configure a director as fallback. A fallback director will try each of the added backends in turn, and return the first one that is healthy. If sticky is set, the director doesn't go back to a higher priority backend coming back to health. Example udir.fallback(); $Method VOID .random() Description Configure a director as random. The random director distributes load over the backends using a weighted random probability distribution. Example udir.random(); $Method VOID .hash(STRING hdr="") Description Configure a director as hash. The director chooses the backend server by computing a hash/digest of the http header in param. Commonly used with ``client.ip`` or a session cookie to get sticky sessions. Example udir.hash("client-identity"); set req.http.client-identity = client.ip; $Method VOID .leastconn(INT slow_start=0) Description Configure a director as least connections. The director chooses the less busy backend server. A weight based on number of connections is used on tcp backend. The slow start optional parameter is defined in seconds. WARNING: need vdi_busy patch for Varnish Example udir.leastconn(30); $Method VOID .add_backend(BACKEND, REAL weight=1.0) Description Add a backend to the director with an optional weight. 1.0 is the defaut value. Example udir.add_backend(backend1); udir.add_backend(backend2, 2.0); $Method VOID .remove_backend(BACKEND) Description Remove a backend from the director. Example udir.remove_backend(backend1); udir.remove_backend(backend2); $Method BACKEND .backend() Description Pick a backend from the director. Example set req.backend_hint = udir.backend(); $Object dyndirector( STRING port = "http", PROBE probe = 0, DURATION connect_timeout = 0, DURATION first_byte_timeout = 0, DURATION between_bytes_timeout = 0, INT max_connections = 0) Description Create a dynamic director. The default load balancing is random. Load balancing method can be changed. Dyndirector inherit from director object: all director's methods can be used. Dynamic director can manipulate dynamic backends. All dynamic backends are created with the same default values (port, probe, timeouts and max_connections). The uniqueness of dynamic backends is carried by the IP. Inherited backends do not interact with dynamic backends. Example new udir = unidirectors.dyndirector() $Method VOID .round_robin() Description Configure a dynamic director as round robin. Example udir.round_robin(); $Method VOID .fallback(BOOL sticky=0) Description Configure a dynamic director as fallback. Example udir.fallback(); $Method VOID .random() Description Configure a dynamic director as random. Example udir.random(); $Method VOID .hash(STRING hdr="") Description Configure a dynamic director as hash. Example udir.hash("client-identity"); set req.http.client-identity = client.ip; $Method VOID .leastconn(INT slow_start=0) Description Configure a dynamic director as least connections. Example udir.leastconn(30); $Method VOID .add_IP(STRING ip, REAL weight=1.0) Description Add a dynamic backend with IP and an optional weight if not already set. It can be removed by update_IPs() or lookup_addr() call. Example udir.add_IP("1.2.3.4") $Method VOID .remove_IP(STRING ip) Remove a dynamic backend with IP. Example udir.remove_IP("1.2.3.4") $Method VOID .update_IPs(STRING) Description Update dynamic backends with list of IP. It replace old ones, or keep unchanged for same IP. Weight of new backends is set to 1. It will replace dynamic backends create with lookup_addr() until the next lookup call. It will replace dynamic backends create with add_IP(). Example udir.update_IPs("1.2.3.4, 1.2.3.5"); $Method VOID .lookup_addr(STRING addr, ACL whitelist = 0, DURATION ttl = 3600) Description Update dynamic backends with DNS lookups with a frequency of ttl. Weight of new backends is set to 1. It will replace dynamic backends create with update_IPs() or add_IP(). Example udir.lookup_addr("prod.mydomaine.live"); $Method BACKEND .backend() Description Pick a backend from the dynamic director. Example set req.backend_hint = udir.backend(); $Method VOID .add_backend(BACKEND, REAL weight=1.0) Description Add a backend to the dynamic director with an optional weight. This backend will be ignored by update_IPs() and lookup_addr() and will remain configured until a remove_backend(); $Method VOID .remove_backend(BACKEND) Description Remove a backend set by add_backend() from the dynamic director. $Method VOID .debug(BOOL enable=0) Description Enable or disable debugging for a dynamic director. $Function BACKEND search_backend(BACKEND, IP) Description Pick a backend matching the IP from the director. WARNING: need vdi_search patch for Varnish Example set req.backend_hint = unidirectors.search(udir.backend(), client.ip); $Function BOOL is_backend(BACKEND) Description Test if we have a backend (healthy or not). Useful to authorise the backends to PURGE itself. Example if (!unidirectors.is_backend(unidirectors.search_backend(req.backend_hint, client.ip))) { return (synth(405)); } $Function STRING backend_type(BACKEND) Description Return the type of the backend. Example set beresp.http.director = unidirectors.backend_type(bereq.backend); $Event vmod_event