blob: ee1dc5232648ef69843087c4ab2fb7bd721eb8bd [file] [log] [blame]
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02001/*
2 * Consistent Hash implementation
3 * Please consult this very well detailed article for more information :
4 * http://www.spiteful.com/2008/03/17/programmers-toolbox-part-3-consistent-hashing/
5 *
6 * Our implementation has to support both weighted hashing and weighted round
7 * robin because we'll use it to replace the previous map-based implementation
8 * which offered both algorithms.
9 *
Willy Tarreau4c14eaa2010-11-24 14:01:45 +010010 * Copyright 2000-2010 Willy Tarreau <w@1wt.eu>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020011 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 *
17 */
18
19#include <common/compat.h>
20#include <common/config.h>
21#include <common/debug.h>
Willy Tarreau4c14eaa2010-11-24 14:01:45 +010022#include <common/standard.h>
Willy Tarreau45cb4fb2009-10-26 21:10:04 +010023#include <eb32tree.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020024
25#include <types/global.h>
26#include <types/server.h>
27
28#include <proto/backend.h>
29#include <proto/queue.h>
30
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020031/* Return next tree node after <node> which must still be in the tree, or be
32 * NULL. Lookup wraps around the end to the beginning. If the next node is the
33 * same node, return NULL. This is designed to find a valid next node before
34 * deleting one from the tree.
35 */
36static inline struct eb32_node *chash_skip_node(struct eb_root *root, struct eb32_node *node)
37{
38 struct eb32_node *stop = node;
39
40 if (!node)
41 return NULL;
42 node = eb32_next(node);
43 if (!node)
44 node = eb32_first(root);
45 if (node == stop)
46 return NULL;
47 return node;
48}
49
50/* Remove all of a server's entries from its tree. This may be used when
51 * setting a server down.
52 */
53static inline void chash_dequeue_srv(struct server *s)
54{
55 while (s->lb_nodes_now > 0) {
56 if (s->lb_nodes_now >= s->lb_nodes_tot) // should always be false anyway
57 s->lb_nodes_now = s->lb_nodes_tot;
58 s->lb_nodes_now--;
59 if (s->proxy->lbprm.chash.last == &s->lb_nodes[s->lb_nodes_now].node)
60 s->proxy->lbprm.chash.last = chash_skip_node(s->lb_tree, s->proxy->lbprm.chash.last);
61 eb32_delete(&s->lb_nodes[s->lb_nodes_now].node);
62 }
63}
64
65/* Adjust the number of entries of a server in its tree. The server must appear
66 * as many times as its weight indicates it. If it's there too often, we remove
67 * the last occurrences. If it's not there enough, we add more occurrences. To
68 * remove a server from the tree, normally call this with eweight=0.
69 */
70static inline void chash_queue_dequeue_srv(struct server *s)
71{
72 while (s->lb_nodes_now > s->eweight) {
73 if (s->lb_nodes_now >= s->lb_nodes_tot) // should always be false anyway
74 s->lb_nodes_now = s->lb_nodes_tot;
75 s->lb_nodes_now--;
76 if (s->proxy->lbprm.chash.last == &s->lb_nodes[s->lb_nodes_now].node)
77 s->proxy->lbprm.chash.last = chash_skip_node(s->lb_tree, s->proxy->lbprm.chash.last);
78 eb32_delete(&s->lb_nodes[s->lb_nodes_now].node);
79 }
80
81 while (s->lb_nodes_now < s->eweight) {
82 if (s->lb_nodes_now >= s->lb_nodes_tot) // should always be false anyway
83 break;
84 if (s->proxy->lbprm.chash.last == &s->lb_nodes[s->lb_nodes_now].node)
85 s->proxy->lbprm.chash.last = chash_skip_node(s->lb_tree, s->proxy->lbprm.chash.last);
86 eb32_insert(s->lb_tree, &s->lb_nodes[s->lb_nodes_now].node);
87 s->lb_nodes_now++;
88 }
89}
90
91/* This function updates the server trees according to server <srv>'s new
92 * state. It should be called when server <srv>'s status changes to down.
93 * It is not important whether the server was already down or not. It is not
94 * important either that the new state is completely down (the caller may not
95 * know all the variables of a server's state).
96 */
97static void chash_set_server_status_down(struct server *srv)
98{
99 struct proxy *p = srv->proxy;
100
Willy Tarreauc5150da2014-05-13 19:27:31 +0200101 if (!srv_lb_status_changed(srv))
Willy Tarreau6b2e11b2009-10-01 07:52:15 +0200102 return;
103
Willy Tarreau87eb1d62014-05-13 18:51:40 +0200104 if (srv_is_usable(srv))
Willy Tarreau6b2e11b2009-10-01 07:52:15 +0200105 goto out_update_state;
106
Willy Tarreau87eb1d62014-05-13 18:51:40 +0200107 if (!srv_was_usable(srv))
Willy Tarreau6b2e11b2009-10-01 07:52:15 +0200108 /* server was already down */
109 goto out_update_backend;
110
Willy Tarreauc93cd162014-05-13 15:54:22 +0200111 if (srv->flags & SRV_F_BACKUP) {
Willy Tarreau6b2e11b2009-10-01 07:52:15 +0200112 p->lbprm.tot_wbck -= srv->prev_eweight;
113 p->srv_bck--;
114
115 if (srv == p->lbprm.fbck) {
116 /* we lost the first backup server in a single-backup
117 * configuration, we must search another one.
118 */
119 struct server *srv2 = p->lbprm.fbck;
120 do {
121 srv2 = srv2->next;
122 } while (srv2 &&
Willy Tarreauc93cd162014-05-13 15:54:22 +0200123 !((srv2->flags & SRV_F_BACKUP) &&
Willy Tarreau87eb1d62014-05-13 18:51:40 +0200124 srv_is_usable(srv2)));
Willy Tarreau6b2e11b2009-10-01 07:52:15 +0200125 p->lbprm.fbck = srv2;
126 }
127 } else {
128 p->lbprm.tot_wact -= srv->prev_eweight;
129 p->srv_act--;
130 }
131
132 chash_dequeue_srv(srv);
133
134out_update_backend:
135 /* check/update tot_used, tot_weight */
136 update_backend_weight(p);
137 out_update_state:
Willy Tarreauc5150da2014-05-13 19:27:31 +0200138 srv_lb_commit_status(srv);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +0200139}
140
141/* This function updates the server trees according to server <srv>'s new
142 * state. It should be called when server <srv>'s status changes to up.
143 * It is not important whether the server was already down or not. It is not
144 * important either that the new state is completely UP (the caller may not
145 * know all the variables of a server's state). This function will not change
146 * the weight of a server which was already up.
147 */
148static void chash_set_server_status_up(struct server *srv)
149{
150 struct proxy *p = srv->proxy;
151
Willy Tarreauc5150da2014-05-13 19:27:31 +0200152 if (!srv_lb_status_changed(srv))
Willy Tarreau6b2e11b2009-10-01 07:52:15 +0200153 return;
154
Willy Tarreau87eb1d62014-05-13 18:51:40 +0200155 if (!srv_is_usable(srv))
Willy Tarreau6b2e11b2009-10-01 07:52:15 +0200156 goto out_update_state;
157
Willy Tarreau87eb1d62014-05-13 18:51:40 +0200158 if (srv_was_usable(srv))
Willy Tarreau6b2e11b2009-10-01 07:52:15 +0200159 /* server was already up */
160 goto out_update_backend;
161
Willy Tarreauc93cd162014-05-13 15:54:22 +0200162 if (srv->flags & SRV_F_BACKUP) {
Willy Tarreau6b2e11b2009-10-01 07:52:15 +0200163 p->lbprm.tot_wbck += srv->eweight;
164 p->srv_bck++;
165
166 if (!(p->options & PR_O_USE_ALL_BK)) {
167 if (!p->lbprm.fbck) {
168 /* there was no backup server anymore */
169 p->lbprm.fbck = srv;
170 } else {
171 /* we may have restored a backup server prior to fbck,
172 * in which case it should replace it.
173 */
174 struct server *srv2 = srv;
175 do {
176 srv2 = srv2->next;
177 } while (srv2 && (srv2 != p->lbprm.fbck));
178 if (srv2)
179 p->lbprm.fbck = srv;
180 }
181 }
182 } else {
183 p->lbprm.tot_wact += srv->eweight;
184 p->srv_act++;
185 }
186
187 /* note that eweight cannot be 0 here */
188 chash_queue_dequeue_srv(srv);
189
190 out_update_backend:
191 /* check/update tot_used, tot_weight */
192 update_backend_weight(p);
193 out_update_state:
Willy Tarreauc5150da2014-05-13 19:27:31 +0200194 srv_lb_commit_status(srv);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +0200195}
196
197/* This function must be called after an update to server <srv>'s effective
198 * weight. It may be called after a state change too.
199 */
200static void chash_update_server_weight(struct server *srv)
201{
202 int old_state, new_state;
203 struct proxy *p = srv->proxy;
204
Willy Tarreauc5150da2014-05-13 19:27:31 +0200205 if (!srv_lb_status_changed(srv))
Willy Tarreau6b2e11b2009-10-01 07:52:15 +0200206 return;
207
208 /* If changing the server's weight changes its state, we simply apply
209 * the procedures we already have for status change. If the state
210 * remains down, the server is not in any tree, so it's as easy as
211 * updating its values. If the state remains up with different weights,
212 * there are some computations to perform to find a new place and
213 * possibly a new tree for this server.
214 */
215
Willy Tarreau87eb1d62014-05-13 18:51:40 +0200216 old_state = srv_was_usable(srv);
217 new_state = srv_is_usable(srv);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +0200218
219 if (!old_state && !new_state) {
Willy Tarreauc5150da2014-05-13 19:27:31 +0200220 srv_lb_commit_status(srv);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +0200221 return;
222 }
223 else if (!old_state && new_state) {
224 chash_set_server_status_up(srv);
225 return;
226 }
227 else if (old_state && !new_state) {
228 chash_set_server_status_down(srv);
229 return;
230 }
231
232 /* only adjust the server's presence in the tree */
233 chash_queue_dequeue_srv(srv);
234
Willy Tarreauc93cd162014-05-13 15:54:22 +0200235 if (srv->flags & SRV_F_BACKUP)
Willy Tarreau6b2e11b2009-10-01 07:52:15 +0200236 p->lbprm.tot_wbck += srv->eweight - srv->prev_eweight;
237 else
238 p->lbprm.tot_wact += srv->eweight - srv->prev_eweight;
239
240 update_backend_weight(p);
Willy Tarreauc5150da2014-05-13 19:27:31 +0200241 srv_lb_commit_status(srv);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +0200242}
243
244/*
245 * This function returns the running server from the CHASH tree, which is at
246 * the closest distance from the value of <hash>. Doing so ensures that even
247 * with a well imbalanced hash, if some servers are close to each other, they
248 * will still both receive traffic. If any server is found, it will be returned.
249 * If no valid server is found, NULL is returned.
250 */
251struct server *chash_get_server_hash(struct proxy *p, unsigned int hash)
252{
253 struct eb32_node *next, *prev;
254 struct server *nsrv, *psrv;
255 struct eb_root *root;
256 unsigned int dn, dp;
257
258 if (p->srv_act)
259 root = &p->lbprm.chash.act;
260 else if (p->lbprm.fbck)
261 return p->lbprm.fbck;
262 else if (p->srv_bck)
263 root = &p->lbprm.chash.bck;
264 else
265 return NULL;
266
Willy Tarreau6b2e11b2009-10-01 07:52:15 +0200267 /* find the node after and the node before */
268 next = eb32_lookup_ge(root, hash);
269 if (!next)
270 next = eb32_first(root);
271 if (!next)
272 return NULL; /* tree is empty */
273
274 prev = eb32_prev(next);
275 if (!prev)
276 prev = eb32_last(root);
277
278 nsrv = eb32_entry(next, struct tree_occ, node)->server;
279 psrv = eb32_entry(prev, struct tree_occ, node)->server;
280 if (nsrv == psrv)
281 return nsrv;
282
283 /* OK we're located between two distinct servers, let's
284 * compare distances between hash and the two servers
285 * and select the closest server.
286 */
287 dp = hash - prev->key;
288 dn = next->key - hash;
289
290 return (dp <= dn) ? psrv : nsrv;
291}
292
293/* Return next server from the CHASH tree in backend <p>. If the tree is empty,
294 * return NULL. Saturated servers are skipped.
295 */
296struct server *chash_get_next_server(struct proxy *p, struct server *srvtoavoid)
297{
298 struct server *srv, *avoided;
299 struct eb32_node *node, *stop, *avoided_node;
300 struct eb_root *root;
301
302 srv = avoided = NULL;
303 avoided_node = NULL;
304
305 if (p->srv_act)
306 root = &p->lbprm.chash.act;
307 else if (p->lbprm.fbck)
308 return p->lbprm.fbck;
309 else if (p->srv_bck)
310 root = &p->lbprm.chash.bck;
311 else
312 return NULL;
313
314 stop = node = p->lbprm.chash.last;
315 do {
316 struct server *s;
317
318 if (node)
319 node = eb32_next(node);
320 if (!node)
321 node = eb32_first(root);
322
323 p->lbprm.chash.last = node;
324 if (!node)
325 /* no node is available */
326 return NULL;
327
Willy Tarreaud16a1b22013-04-12 14:46:51 +0200328 /* Note: if we came here after a down/up cycle with no last
329 * pointer, and after a redispatch (srvtoavoid is set), we
330 * must set stop to non-null otherwise we can loop forever.
331 */
332 if (!stop)
333 stop = node;
334
Willy Tarreau6b2e11b2009-10-01 07:52:15 +0200335 /* OK, we have a server. However, it may be saturated, in which
336 * case we don't want to reconsider it for now, so we'll simply
337 * skip it. Same if it's the server we try to avoid, in which
338 * case we simply remember it for later use if needed.
339 */
340 s = eb32_entry(node, struct tree_occ, node)->server;
341 if (!s->maxconn || (!s->nbpend && s->served < srv_dynamic_maxconn(s))) {
342 if (s != srvtoavoid) {
343 srv = s;
344 break;
345 }
346 avoided = s;
347 avoided_node = node;
348 }
349 } while (node != stop);
350
351 if (!srv) {
352 srv = avoided;
353 p->lbprm.chash.last = avoided_node;
354 }
355
356 return srv;
357}
358
359/* This function is responsible for building the active and backup trees for
360 * constistent hashing. The servers receive an array of initialized nodes
361 * with their assigned keys. It also sets p->lbprm.wdiv to the eweight to
362 * uweight ratio.
363 */
364void chash_init_server_tree(struct proxy *p)
365{
366 struct server *srv;
367 struct eb_root init_head = EB_ROOT;
368 int node;
369
370 p->lbprm.set_server_status_up = chash_set_server_status_up;
371 p->lbprm.set_server_status_down = chash_set_server_status_down;
372 p->lbprm.update_server_eweight = chash_update_server_weight;
373 p->lbprm.server_take_conn = NULL;
374 p->lbprm.server_drop_conn = NULL;
375
376 p->lbprm.wdiv = BE_WEIGHT_SCALE;
377 for (srv = p->srv; srv; srv = srv->next) {
Willy Tarreau004e0452013-11-21 11:22:01 +0100378 srv->eweight = (srv->uweight * p->lbprm.wdiv + p->lbprm.wmult - 1) / p->lbprm.wmult;
Willy Tarreauc5150da2014-05-13 19:27:31 +0200379 srv_lb_commit_status(srv);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +0200380 }
381
382 recount_servers(p);
383 update_backend_weight(p);
384
385 p->lbprm.chash.act = init_head;
386 p->lbprm.chash.bck = init_head;
387 p->lbprm.chash.last = NULL;
388
389 /* queue active and backup servers in two distinct groups */
390 for (srv = p->srv; srv; srv = srv->next) {
Willy Tarreauc93cd162014-05-13 15:54:22 +0200391 srv->lb_tree = (srv->flags & SRV_F_BACKUP) ? &p->lbprm.chash.bck : &p->lbprm.chash.act;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +0200392 srv->lb_nodes_tot = srv->uweight * BE_WEIGHT_SCALE;
393 srv->lb_nodes_now = 0;
394 srv->lb_nodes = (struct tree_occ *)calloc(srv->lb_nodes_tot, sizeof(struct tree_occ));
395
396 for (node = 0; node < srv->lb_nodes_tot; node++) {
397 srv->lb_nodes[node].server = srv;
Willy Tarreau4c14eaa2010-11-24 14:01:45 +0100398 srv->lb_nodes[node].node.key = full_hash(srv->puid * SRV_EWGHT_RANGE + node);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +0200399 }
400
Willy Tarreau87eb1d62014-05-13 18:51:40 +0200401 if (srv_is_usable(srv))
Willy Tarreau6b2e11b2009-10-01 07:52:15 +0200402 chash_queue_dequeue_srv(srv);
403 }
404}