Skip to content

Commit

Permalink
Least connections algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
karlvr committed Nov 13, 2024
1 parent dc68d3b commit 1b02912
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 4 deletions.
76 changes: 73 additions & 3 deletions src/vmod_dynamic.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,57 @@ dom_wait_active(struct dynamic_domain *dom)
DBG(NULL, dom, "wait-active ret %d", ret);
}

/* find a healthy dynamic_ref with the least connections */
static struct dynamic_ref *
dom_find_leastconn(VRT_CTX, struct dynamic_domain *dom)
{
struct dynamic_ref *next, *start, *best_next;
unsigned most_connections_available;

CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(dom, DYNAMIC_DOMAIN_MAGIC);

dom_wait_active(dom);

if (dom->status > DYNAMIC_ST_ACTIVE)
return (NULL);

next = dom->current;
start = next;
best_next = next;
most_connections_available = 0;

do {
CHECK_OBJ_ORNULL(next, DYNAMIC_REF_MAGIC);
if (next != NULL)
next = VTAILQ_NEXT(next, list);
if (next == NULL)
next = VTAILQ_FIRST(&dom->refs);
if (next == NULL)
break;

if (next->dir != creating && next->dir != NULL && VRT_Healthy(ctx, next->dir, NULL)) {
if (VALID_OBJ((struct backend *)next->dir->priv, BACKEND_MAGIC)) {
struct backend *be;
unsigned connections_available;

CAST_OBJ_NOTNULL(be, next->dir->priv, BACKEND_MAGIC);
connections_available = be->max_connections > 0 ? be->max_connections - be->n_conn : - be->n_conn;
if (connections_available > most_connections_available) {
best_next = next;
most_connections_available = connections_available;
}
}
}
} while (next != start);

if (best_next != NULL) {
return best_next;
} else {
return NULL;
}
}

/* find a healthy dynamic_ref */
static struct dynamic_ref *
dom_find(VRT_CTX, struct dynamic_domain *dom, struct dynamic_ref *start,
Expand Down Expand Up @@ -330,7 +381,7 @@ static VCL_BACKEND v_matchproto_(vdi_resolve_f)
dom_resolve(VRT_CTX, VCL_BACKEND d)
{
struct dynamic_domain *dom;
struct dynamic_ref *r;
struct dynamic_ref *r = NULL;
VCL_BACKEND n = NULL;

CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
Expand All @@ -348,7 +399,12 @@ dom_resolve(VRT_CTX, VCL_BACKEND d)
dynamic_gc_expired(dom->obj);

Lck_Lock(&dom->mtx);
r = dom_find(ctx, dom, dom->current, NULL, NULL, 1);
if (dom->obj->algorithm == LEAST) {
r = dom_find_leastconn(ctx, dom);
}
if (r == NULL) {
r = dom_find(ctx, dom, dom->current, NULL, NULL, 1);
}
dom->current = r;
if (r != NULL)
VRT_Assign_Backend(&n, r->dir);
Expand Down Expand Up @@ -1306,6 +1362,18 @@ dynamic_ttl_parse(const char *s)
INCOMPL();
}

static inline enum dynamic_algorithm_e
dynamic_algorithm_parse(const char *algorithm_s)
{
switch (algorithm_s[0]) {
case 'R': return RR; break;
case 'L': return LEAST; break;
default: INCOMPL();
}
INCOMPL();
NEEDLESS(return(0));
}


VCL_VOID v_matchproto_()
vmod_director__init(VRT_CTX,
Expand All @@ -1329,7 +1397,8 @@ vmod_director__init(VRT_CTX,
VCL_DURATION retry_after,
VCL_BACKEND via,
VCL_INT keep,
VCL_STRING authority)
VCL_STRING authority,
VCL_ENUM algorithm_arg)
{
struct vmod_dynamic_director *obj;

Expand Down Expand Up @@ -1402,6 +1471,7 @@ vmod_director__init(VRT_CTX,
obj->max_connections = (unsigned)max_connections;
obj->proxy_header = (unsigned)proxy_header;
obj->ttl_from = dynamic_ttl_parse(ttl_from_arg);
obj->algorithm = dynamic_algorithm_parse(algorithm_arg);
obj->keep = (unsigned)keep;

if (resolver != NULL) {
Expand Down
6 changes: 6 additions & 0 deletions src/vmod_dynamic.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ enum dynamic_ttl_e {
TTL_E_MAX
};

enum dynamic_algorithm_e {
RR,
LEAST
};

struct dynamic_domain {
unsigned magic;
#define DYNAMIC_DOMAIN_MAGIC 0x1bfe1345
Expand Down Expand Up @@ -203,6 +208,7 @@ struct vmod_dynamic_director {
const struct res_cb *resolver;
struct VPFX(dynamic_resolver) *resolver_inst;
enum dynamic_ttl_e ttl_from;
enum dynamic_algorithm_e algorithm;
unsigned debug;
};

Expand Down
13 changes: 12 additions & 1 deletion src/vmod_dynamic.vcc
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,8 @@ $Object director(
DURATION retry_after = 30,
BACKEND via = NULL,
INT keep = 3,
STRING authority = NULL)
STRING authority = NULL,
ENUM { RR, LEAST } algorithm = "RR")

Description
Create a DNS director.
Expand Down Expand Up @@ -364,6 +365,16 @@ Parameters:
a high positive value (``UINT_MAX``, usually 4 294 967 295,
see :ref:`limits.h(7POSIX)`).

- *algorithm* (default: RR)

Load balancing algorithm to use.

``RR`` cycles between health backends.

``LEAST`` chooses the healthy backend with the most number of connections available
(i.e. the difference between ``max_connections`` and the backends current connections).
The algorithm works in a similar way if ``max_connections`` isn't set.

Parameters to set attributes of backends

See varnish documentation for details
Expand Down

0 comments on commit 1b02912

Please sign in to comment.