[MINOR] acl: add fe_conn, be_conn, queue, avg_queue

These ACLs are used to check the number of active connections on the
frontend, backend or in a backend's queue. The avg_queue returns the
average number of queued connections per server, and for this, divides
the total number of queued connections by the number of alive servers.

The dst_conn ACL has been slightly changed to more reflect its name and
original usage, which is to return the number of connections on the
destination address/port (the socket) and not the whole frontend.
This commit is contained in:
Willy Tarreau 2009-10-10 12:02:45 +02:00
parent 6b2e11be1e
commit a36af91951
3 changed files with 148 additions and 7 deletions

View File

@ -5041,10 +5041,30 @@ dst_port <integer>
to a different backend for some alternative ports.
dst_conn <integer>
Applies to the number of currently established connections on the frontend,
Applies to the number of currently established connections on the same socket
including the one being evaluated. It can be used to either return a sorry
page before hard-blocking, or to use a specific backend to drain new requests
when the farm is considered saturated.
when the socket is considered saturated. This offers the ability to assign
different limits to different listening ports or addresses. See also the
"fe_conn" and "be_conn" criteria.
fe_conn <integer>
fe_conn(frontend) <integer>
Applies to the number of currently established connections on the frontend,
possibly including the connection being evaluated. If no frontend name is
specified, the current one is used. But it is also possible to check another
frontend. It can be used to either return a sorry page before hard-blocking,
or to use a specific backend to drain new requests when the farm is
considered saturated. See also the "dst_conn", "be_conn" and "fe_sess_rate"
criteria.
be_conn <integer>
be_conn(frontend) <integer>
Applies to the number of currently established connections on the backend,
possibly including the connection being evaluated. If no backend name is
specified, the current one is used. But it is also possible to check another
backend. It can be used to use a specific farm when the nominal one is full.
See also the "fe_conn", "queue" and "be_sess_rate" criteria.
nbsrv <integer>
nbsrv(backend) <integer>
@ -5063,19 +5083,43 @@ connslots(backend) <integer>
'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
Note that while "fe_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
available "connslots". Also, whereas "nbsrv" only measures servers that are
actually *down*, this acl is more fine-grained and looks into the number of
available connection slots as well.
available connection slots as well. See also "queue" and "avg_queue".
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.
queue <integer>
queue(frontend) <integer>
Returns the total number of queued connections of the designated backend,
including all the connections in server queues. If no backend name is
specified, the current one is used, but it is also possible to check another
one. This can be used to take actions when queuing goes above a known level,
generally indicating a surge of traffic or a massive slowdown on the servers.
One possible action could be to reject new users but still accept old ones.
See also the "avg_queue", "be_conn", and "be_sess_rate" criteria.
avg_queue <integer>
avg_queue(frontend) <integer>
Returns the total number of queued connections of the designated backend
divided by the number of active servers. This is very similar to "queue"
except that the size of the farm is considered, in order to give a more
accurate measurement of the time it may take for a new connection to be
processed. The main usage is to return a sorry page to new users when it
becomes certain they will get a degraded service. Note that in the event
there would not be any active server anymore, we would consider twice the
number of queued connections as the measured value. This is a fair estimate,
as we expect one server to get back soon anyway, but we still prefer to send
new traffic to another backend if in better shape. See also the "queue",
"be_conn", and "be_sess_rate" criteria.
fe_sess_rate <integer>
fe_sess_rate(frontend) <integer>
Returns true when the session creation rate on the current or the named

View File

@ -1188,7 +1188,7 @@ acl_fetch_connslots(struct proxy *px, struct session *l4, void *l7, int dir,
test->i = 0;
iterator = px->srv;
while (iterator) {
if ((iterator->state & 1) == 0) {
if ((iterator->state & SRV_RUNNING) == 0) {
iterator = iterator->next;
continue;
}
@ -1243,6 +1243,99 @@ acl_fetch_be_sess_rate(struct proxy *px, struct session *l4, void *l7, int dir,
return 1;
}
/* set test->i to the number of concurrent connections on the frontend */
static int
acl_fetch_fe_conn(struct proxy *px, struct session *l4, void *l7, int dir,
struct acl_expr *expr, struct acl_test *test)
{
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_FE) && !strcmp(px->id, expr->arg.str))
break;
}
if (!px)
return 0;
test->i = px->feconn;
return 1;
}
/* set test->i to the number of concurrent connections on the backend */
static int
acl_fetch_be_conn(struct proxy *px, struct session *l4, void *l7, int dir,
struct acl_expr *expr, struct acl_test *test)
{
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 = px->beconn;
return 1;
}
/* set test->i to the total number of queued connections on the backend */
static int
acl_fetch_queue_size(struct proxy *px, struct session *l4, void *l7, int dir,
struct acl_expr *expr, struct acl_test *test)
{
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 = px->totpend;
return 1;
}
/* set test->i to the total number of queued connections on the backend divided
* by the number of running servers and rounded up. If there is no running
* server, we return twice the total, just as if we had half a running server.
* This is more or less correct anyway, since we expect the last server to come
* back soon.
*/
static int
acl_fetch_avg_queue_size(struct proxy *px, struct session *l4, void *l7, int dir,
struct acl_expr *expr, struct acl_test *test)
{
int nbsrv;
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;
if (px->srv_act)
nbsrv = px->srv_act;
else if (px->lbprm.fbck)
nbsrv = 1;
else
nbsrv = px->srv_bck;
if (nbsrv > 0)
test->i = (px->totpend + nbsrv - 1) / nbsrv;
else
test->i = px->totpend * 2;
return 1;
}
/* Note: must not be declared <const> as its list will be overwritten */
static struct acl_kw_list acl_kws = {{ },{
@ -1250,6 +1343,10 @@ static struct acl_kw_list acl_kws = {{ },{
{ "connslots", acl_parse_int, acl_fetch_connslots, acl_match_int, ACL_USE_NOTHING },
{ "fe_sess_rate", acl_parse_int, acl_fetch_fe_sess_rate, acl_match_int, ACL_USE_NOTHING },
{ "be_sess_rate", acl_parse_int, acl_fetch_be_sess_rate, acl_match_int, ACL_USE_NOTHING },
{ "fe_conn", acl_parse_int, acl_fetch_fe_conn, acl_match_int, ACL_USE_NOTHING },
{ "be_conn", acl_parse_int, acl_fetch_be_conn, acl_match_int, ACL_USE_NOTHING },
{ "queue", acl_parse_int, acl_fetch_queue_size, acl_match_int, ACL_USE_NOTHING },
{ "avg_queue", acl_parse_int, acl_fetch_avg_queue_size, acl_match_int, ACL_USE_NOTHING },
{ NULL, NULL, NULL, NULL },
}};

View File

@ -593,12 +593,12 @@ acl_fetch_dport(struct proxy *px, struct session *l4, void *l7, int dir,
}
/* set test->i to the number of connexions to the proxy */
/* set test->i to the number of connexions to the same listening socket */
static int
acl_fetch_dconn(struct proxy *px, struct session *l4, void *l7, int dir,
struct acl_expr *expr, struct acl_test *test)
{
test->i = px->feconn;
test->i = l4->listener->nbconn;
return 1;
}