Load Balancing#
Angie distributes client requests across a group of upstream servers described by an upstream block. Which server handles a given request is decided by the group's balancing method.
This guide covers HTTP balancing, configured in the HTTP Upstream module. Balancing of TCP and UDP sessions works the same way and is configured in the Stream Upstream module; differences are noted where they matter.
A group uses exactly one balancing method. If a block names more than one, the
last one takes effect and Angie logs A method determines how Angie picks a server for each request, and each method
accepts its own set of server parameters. A parameter that a method
does not support is not ignored: Angie refuses to start and reports
Method Distributes requests by Level Position in a weighted rotation. The default; no directive. L4, L7 Hash of a key you choose, such as a URI or a header. L4, L7 Hash of the client address. L7 Fewest active connections per unit of weight. L4, L7 Chance, in proportion to weight. L4, L7 Chance, in inverse proportion to average response time. L4, L7 feedback (PRO) Chance, in proportion to a value the servers report. L4, L7 Every method above is available in Angie except Round robin is the default method: Angie uses it whenever a group names no
other method, and it has no directive of its own. Angie rotates through the
group's servers, giving each one a share of the rotation proportional to its
Of every seven requests, five go to Round robin is also the fallback for other methods. When hash,
ip_hash, or random cannot settle on a usable server, they
hand the choice to round robin. The hash method sends all requests whose keys have the same hash to the
same server. This helps when the group's servers cache responses themselves,
such as caching proxies or memcached nodes. While the group's membership stays
the same, requests for a given URI always reach the same server, so its response
is cached on that one server rather than on every server in the group. The key is any string of variables. Weights work by
giving a heavier server proportionally more of the key space. Without Note A server's ring positions are computed from its name as written in the
Without The ip_hash method keys on the client address: the first three octets
of an IPv4 address, or the whole IPv6 address. Requests from one client reach
one server for as long as that server is available. It has no consistent-hashing mode, so changing the set of servers may redirect
many clients to other servers. To take a server out of service while preserving
the rest of the mapping, mark it The least_conn method picks the server with the fewest active
connections per unit of weight — it minimizes the ratio of connections to
weight, not the raw count. A server at Only connections currently carrying a request count. Idle keepalive
connections do not. Use it when requests differ widely in how long they occupy a server: large
downloads, long polling, WebSocket. Round robin sends each server the same
number of requests per unit of weight, but that number says little about load
when some requests hold a server for milliseconds and others for minutes;
The random method picks a server at random, in proportion to weight.
Over many requests the distribution matches the weights. The This matters when several balancers front the same servers without sharing
state. Each balancer choosing the single least-loaded server drives them all at
the same target; choosing the better of two random candidates spreads the load
instead. With a single balancer, least_conn is the simpler choice. Note The least_time method favors servers that answer quickly. Its mode
sets what is measured: A group whose servers are compared by the time to the response header: The measurement is an exponentially weighted moving average, so a single slow
response does not move a server far. The response_time_factor
directive, or the Two properties are worth knowing before you choose it. It does not simply pick the fastest server. A server's chance of receiving
the request is inversely proportional to its average response time. Even a
consistently slow server keeps a small share — roughly one percent of what an
average server receives, so about one request in 100 x N for a group of N
servers. This is deliberate: a server that received nothing would never produce
a new measurement, and could never be found to have recovered. It rejects In Stream, least_time accepts a different set of modes:
The feedback (PRO) method lets the servers themselves say how much work they
want. Angie reads a value out of each response — typically a header — and gives
a server a share of requests in proportion to it, averaged the same way
least_time averages response time. Warning The value is read in the direction you would expect for spare capacity:
a higher reported value earns a larger share. If your metric rises as the
server gets busier — CPU load, queue depth — add the The Angie judges a server by the outcome of requests sent to it. If an attempt
matches a retry condition and the attempt limit is not exhausted, Angie can pass
the request to a different server. The proxy_next_upstream directive and
its counterparts define those conditions; proxy_next_upstream_tries
and proxy_next_upstream_timeout limit the number and duration of
attempts. max_fails unsuccessful attempts within
fail_timeout mark a server unavailable for that same
period, after which it is tried again. The defaults are one attempt and ten
seconds. What counts as an unsuccessful attempt is set by
proxy_next_upstream and its counterparts. Setting Note Below the max_fails threshold, an individual failure still
reduces a server's share, which recovers gradually. Without
slow_start, Angie reduces the effective weight used by
round robin and Passive checks learn about a server only from client requests: a failure is
detected after client requests to the server have already failed, and a
recovery only when a client request is sent to it again. Active checks,
available in Angie PRO, contact the servers on a schedule regardless of client
traffic, and notice both failure and recovery without spending client requests
on either. A check is set up by the upstream_probe (PRO) directive in the same
Every five seconds, Angie requests Check responses can also feed the feedback method through its
A server found unhealthy is excluded from selection by every balancing method.
After a configuration reload, checks start over. By default, a server keeps
receiving requests without waiting for the first check after the reload. If
Servers marked Every request starts at the primary servers and reaches the backup group only
when no primary server can take it. There is no lasting failover mode to return
from — as soon as a primary server passes its health check again, the next
request uses it. Angie PRO can invert this with backup_switch (PRO) The The slow_start parameter ramps a recovered server back up to
its full weight over a period instead of restoring it at once, which keeps a
cold cache or a just-started process from being hit at full rate: It most often applies after a server has been marked unavailable and has
recovered; an individual failure also moves the server backward on the same
ramp (see Failure and Recovery). It works only with the methods marked in the
To take a server out of rotation deliberately, use load balancing method redefined; a
block that names none uses Weighted Round Robin.Choosing a Method#
balancing method does not support parameter. Check this table before
combining a method with weight, slow_start, or backup.weightslow_startbackupfeedback, which requires
Angie PRO. ip_hash has no Stream counterpart; use hash with
$remote_addr instead.Balancing Methods#
Weighted Round Robin#
weight:upstream backend {
zone backend 1m;
server backend1.example.com weight=5;
server backend2.example.com;
server backend3.example.com;
}
backend1.example.com and one to each
of the others. The distribution is smooth: a higher-weight server's requests
are spread across the rotation rather than sent in a single burst, so the group
never sees five consecutive requests for one server followed by two for the
rest.hash#
upstream backend {
zone backend 1m;
hash $request_uri consistent;
server backend1.example.com;
server backend2.example.com;
}
consistent, Angie maps the key's hash onto a range as long as
the group's total weight, where each server holds a segment as long as its
weight. Adding or removing a server changes that total and therefore re-maps
many keys beyond those assigned to the added or removed server: their cached
responses stay on servers that no longer receive requests for them. With consistent,
Angie places the servers on a ketama
ring instead, and removing a server re-maps only the keys that server held.server directive, not from the addresses the name resolves to. All
addresses of one name share those positions, so the name occupies as much of
the ring as a single server of the same weight. When a key lands on one of
the name's positions, Angie picks one of its addresses by round robin.consistent, each address counts as a separate server with its
own weight, and the hash is mapped onto the total weight of all addresses. A
name that resolves to several addresses therefore receives a share
proportional to the number of those addresses.ip_hash#
down rather than deleting its line:upstream backend {
zone backend 1m;
ip_hash;
server backend1.example.com;
server backend2.example.com down;
server backend3.example.com;
}
least_conn#
weight=2 holding 15 connections
is therefore preferred over one at weight=1 holding 10. When several
servers tie, they are tried in turn by weighted round robin.least_conn counts the requests a server is handling right now. If the
servers instead differ in speed, use least_time.random#
two parameter picks two servers at random and then takes whichever
of the two has fewer active connections per unit of weight:upstream backend {
zone backend 1m;
random two;
server backend1.example.com;
server backend2.example.com;
server backend3.example.com;
}
random two least_conn is accepted for compatibility and behaves
exactly like random two; comparing active connections is the only
mode two has.least_time#
header is the time to receive the response
header, last_byte the time to receive the whole response.upstream backend {
zone backend 1m;
least_time header;
server backend1.example.com;
server backend2.example.com;
}
factor parameter, sets how much weight the accumulated
history keeps against each new measurement: a high factor reacts slowly, a low
one forgets quickly.weight. A group that combines least_time with
weight= on any server will not start. Response time already reflects how
much load a server is absorbing, so there is nothing left for a weight to
express.connect (the time to establish a connection to the server),
first_byte (the time to receive the first byte of data from the
server), and last_byte (the time until the session ends);
header is not available.feedback#
upstream backend {
zone backend 1m;
feedback $upstream_http_x_capacity;
server backend1.example.com;
server backend2.example.com;
}
inverse
parameter, or you will send the most traffic to the most loaded server.account parameter selects which responses feed the average, which
lets you drive balancing from upstream_probe (PRO) responses rather than from
client traffic.Failure and Recovery#
Passive health checks#
max_fails=0 disables the check for that server: it is never
marked unavailable.least_conn, then restores it over subsequent
requests. With slow_start, each failure moves the server backward on
the time-based ramp used by every method that accepts the parameter. Both
behaviors require max_fails greater than one: at the default value of
one, the first failure marks the server unavailable, so there is no
intermediate state.Active health checks#
location block that passes requests to the group; the group itself
needs a shared memory zone:upstream backend {
zone backend 1m;
server backend1.example.com;
server backend2.example.com;
}
map $upstream_status $good {
200 "1";
}
server {
listen 80;
location / {
proxy_pass http://backend;
upstream_probe backend_probe uri=/health interval=5s
test=$good fails=3 passes=2;
}
}
/health from each server in the
group. Three failed checks in a row mark a server unhealthy; two passed checks
in a row return it to service. Without the test parameter, a check
fails only when a client request in this location would count as an
unsuccessful attempt. By default, proxy_next_upstream counts only an
error or a timeout, so a 500 or 503 response does not fail the
check. Here,
test=$good passes the check only if the server responds with
200: for any other status, map leaves the variable empty.account parameter.upstream_probe has the essential parameter, the server receives
no requests until the check first finds it healthy (in this example, after two
passed checks in a row); adding persistent, which works only together
with essential, lifts this wait for servers that were healthy before
the reload, because their health flag is kept in the zone (see
State Shared Between Worker Processes).Backup servers#
backup are held in reserve:upstream backend {
zone backend 1m;
server backend1.example.com;
server backend2.example.com;
server backup1.example.com backup;
}
permanent, which
keeps sending requests to the group that last served them. Without a time
argument the switch never reverts on its own; with permanent=time,
Angie sends one request back to the primary group after that interval to see
whether it has recovered.backup parameter is rejected by hash, ip_hash
and random.Returning a server to service#
server backend1.example.com slow_start=30s;
slow_start column under Choosing a Method. Unlike some other
implementations, it does not require the zone directive.down; to stop sending
it new traffic while letting bound sessions finish, use drain.