to handle some load. It is useful to report a failure when combined with
"monitor fail".
+connslots <integer>
+connslots(backend) <integer>
+ The basic idea here is to be able to measure the number of connection "slots"
+ still available (connection, + queue) - so that anything beyond that (intended
+ usage; see "use_backend" keyword) can be redirected to a different backend.
+
+ 'connslots' = number of available server connection slots, + number of available
+ server queue slots.
+
+ *Note that while "dst_conn" may be used, "connslots" comes in especially useful
+ when you have a case of traffic going to one single ip, splitting into multiple
+ backends (perhaps using acls to do name-based load balancing) - and you want to
+ be able to differentiate between different backends, and their "connslots"
+ available. Also, whereas "nbsrv" only measures servers that are actually *down*,
+ this acl is more fine-grained - and looks into the number of conn slots available
+ as well.
+
+ *OTHER CAVEATS AND NOTES: at this point in time, the code does not take care of
+ dynamic connections. Also, if any of the server maxconn, or maxqueue is 0, then
+ this acl clearly does not make sense - in which case the value returned will be -1.
+
2.3.5.2) Matching contents at Layer 4
-------------------------------------
return 1;
}
+/* set test->i to the number of enabled servers on the proxy */
+static int
+acl_fetch_connslots(struct proxy *px, struct session *l4, void *l7, int dir,
+ struct acl_expr *expr, struct acl_test *test)
+{
+ struct server *iterator;
+ test->flags = ACL_TEST_F_VOL_TEST;
+ if (expr->arg_len) {
+ /* another proxy was designated, we must look for it */
+ for (px = proxy; px; px = px->next)
+ if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->arg.str))
+ break;
+ }
+ if (!px)
+ return 0;
+
+ test->i = 0;
+ iterator = px->srv;
+ while (iterator) {
+ if ((iterator->state & 1) == 0) {
+ iterator = iterator->next;
+ continue;
+ }
+ if (iterator->maxconn == 0 || iterator->maxqueue == 0) {
+ test->i = -1;
+ return 1;
+ }
+
+ test->i += (iterator->maxconn - iterator->cur_sess)
+ + (iterator->maxqueue - iterator->nbpend);
+ iterator = iterator->next;
+ }
+
+ return 1;
+}
+
/* Note: must not be declared <const> as its list will be overwritten */
static struct acl_kw_list acl_kws = {{ },{
- { "nbsrv", acl_parse_int, acl_fetch_nbsrv, acl_match_int, ACL_USE_NOTHING },
+ { "nbsrv", acl_parse_int, acl_fetch_nbsrv, acl_match_int, ACL_USE_NOTHING },
+ { "connlots", acl_parse_int, acl_fetch_connslots, acl_match_int, ACL_USE_NOTHING },
{ NULL, NULL, NULL, NULL },
}};