mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-01-03 18:52:04 +00:00
[MEDIUM] continous statistics
By default, counters used for statistics calculation are incremented only when a session finishes. It works quite well when serving small objects, but with big ones (for example large images or archives) or with A/V streaming, a graph generated from haproxy counters looks like a hedgehog. This patch implements a contstats (continous statistics) option. When set counters get incremented continuously, during a whole session. Recounting touches a hotpath directly so it is not enabled by default, as it has small performance impact (~0.5%).
This commit is contained in:
parent
5df518788d
commit
583bc96606
@ -266,6 +266,7 @@ option abortonclose X - X X
|
|||||||
option allbackups X - X X
|
option allbackups X - X X
|
||||||
option checkcache X - X X
|
option checkcache X - X X
|
||||||
option clitcpka X X X -
|
option clitcpka X X X -
|
||||||
|
option contstats X X X -
|
||||||
option dontlognull X X X -
|
option dontlognull X X X -
|
||||||
option forceclose X - X X
|
option forceclose X - X X
|
||||||
option forwardfor X X X X
|
option forwardfor X X X X
|
||||||
@ -324,6 +325,15 @@ usesrc X - X X
|
|||||||
----------------------+----------+----------+---------+---------
|
----------------------+----------+----------+---------+---------
|
||||||
keyword defaults frontend listen backend
|
keyword defaults frontend listen backend
|
||||||
|
|
||||||
|
option contstats
|
||||||
|
By default, counters used for statistics calculation are incremented
|
||||||
|
only when a session finishes. It works quite well when serving small
|
||||||
|
objects, but with big ones (for example large images or archives) or
|
||||||
|
with A/V streaming, a graph generated from haproxy counters looks like
|
||||||
|
a hedgehog. With this option enabled counters get incremented continuously,
|
||||||
|
during a whole session. Recounting touches a hotpath directly so
|
||||||
|
it is not enabled by default, as it has small performance impact (~0.5%).
|
||||||
|
|
||||||
|
|
||||||
2.1) using ACLs
|
2.1) using ACLs
|
||||||
---------------
|
---------------
|
||||||
|
@ -33,6 +33,8 @@ void session_free(struct session *s);
|
|||||||
/* perform minimal intializations, report 0 in case of error, 1 if OK. */
|
/* perform minimal intializations, report 0 in case of error, 1 if OK. */
|
||||||
int init_session();
|
int init_session();
|
||||||
|
|
||||||
|
void session_process_counters(struct session *s);
|
||||||
|
|
||||||
#endif /* _PROTO_SESSION_H */
|
#endif /* _PROTO_SESSION_H */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -57,6 +57,7 @@
|
|||||||
#define PR_O_TPXY_CIP 0x04000000 /* bind to the client's IP address when connect()ing */
|
#define PR_O_TPXY_CIP 0x04000000 /* bind to the client's IP address when connect()ing */
|
||||||
#define PR_O_TPXY_CLI 0x06000000 /* bind to the client's IP+port when connect()ing */
|
#define PR_O_TPXY_CLI 0x06000000 /* bind to the client's IP+port when connect()ing */
|
||||||
#define PR_O_TPXY_MASK 0x06000000 /* bind to a non-local address when connect()ing */
|
#define PR_O_TPXY_MASK 0x06000000 /* bind to a non-local address when connect()ing */
|
||||||
|
|
||||||
#define PR_O_TCPSPLICE 0x08000000 /* delegate data transfer to linux kernel's tcp_splice */
|
#define PR_O_TCPSPLICE 0x08000000 /* delegate data transfer to linux kernel's tcp_splice */
|
||||||
|
|
||||||
/* BALANCE: exclusive values */
|
/* BALANCE: exclusive values */
|
||||||
@ -68,6 +69,7 @@
|
|||||||
#define PR_O_BALANCE_L7 0x40000000 /* mask to match layer7-based algorithms */
|
#define PR_O_BALANCE_L7 0x40000000 /* mask to match layer7-based algorithms */
|
||||||
#define PR_O_BALANCE 0x70000000 /* mask to extract BALANCE algorithm */
|
#define PR_O_BALANCE 0x70000000 /* mask to extract BALANCE algorithm */
|
||||||
|
|
||||||
|
#define PR_O_CONTSTATS 0x80000000 /* continous counters */
|
||||||
|
|
||||||
#endif /* _TYPES_BACKEND_H */
|
#endif /* _TYPES_BACKEND_H */
|
||||||
|
|
||||||
|
@ -98,6 +98,7 @@ static const struct {
|
|||||||
{ "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
|
{ "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
|
||||||
{ "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
|
{ "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
|
||||||
{ "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
|
{ "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
|
||||||
|
{ "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
|
||||||
{ "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
|
{ "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
|
||||||
{ "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
|
{ "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
|
||||||
{ "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
|
{ "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
|
||||||
|
@ -613,6 +613,10 @@ void process_session(struct task *t, struct timeval *next)
|
|||||||
} while (fsm_resync);
|
} while (fsm_resync);
|
||||||
|
|
||||||
if (likely(s->cli_state != CL_STCLOSE || s->srv_state != SV_STCLOSE)) {
|
if (likely(s->cli_state != CL_STCLOSE || s->srv_state != SV_STCLOSE)) {
|
||||||
|
|
||||||
|
if ((s->fe->options & PR_O_CONTSTATS) && (s->flags & SN_BE_ASSIGNED))
|
||||||
|
session_process_counters(s);
|
||||||
|
|
||||||
s->req->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
|
s->req->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
|
||||||
s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
|
s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
|
||||||
|
|
||||||
@ -651,21 +655,7 @@ void process_session(struct task *t, struct timeval *next)
|
|||||||
}
|
}
|
||||||
|
|
||||||
s->logs.t_close = tv_ms_elapsed(&s->logs.tv_accept, &now);
|
s->logs.t_close = tv_ms_elapsed(&s->logs.tv_accept, &now);
|
||||||
if (s->req != NULL)
|
session_process_counters(s);
|
||||||
s->logs.bytes_in = s->req->total;
|
|
||||||
if (s->rep != NULL)
|
|
||||||
s->logs.bytes_out = s->rep->total;
|
|
||||||
|
|
||||||
s->fe->bytes_in += s->logs.bytes_in;
|
|
||||||
s->fe->bytes_out += s->logs.bytes_out;
|
|
||||||
if (s->be != s->fe) {
|
|
||||||
s->be->bytes_in += s->logs.bytes_in;
|
|
||||||
s->be->bytes_out += s->logs.bytes_out;
|
|
||||||
}
|
|
||||||
if (s->srv) {
|
|
||||||
s->srv->bytes_in += s->logs.bytes_in;
|
|
||||||
s->srv->bytes_out += s->logs.bytes_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* let's do a final log if we need it */
|
/* let's do a final log if we need it */
|
||||||
if (s->logs.logwait &&
|
if (s->logs.logwait &&
|
||||||
@ -3096,6 +3086,7 @@ int process_srv(struct session *t)
|
|||||||
http_sess_log(t);
|
http_sess_log(t);
|
||||||
else
|
else
|
||||||
tcp_sess_log(t);
|
tcp_sess_log(t);
|
||||||
|
t->logs.bytes_in = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note: we must not try to cheat by jumping directly to DATA,
|
/* Note: we must not try to cheat by jumping directly to DATA,
|
||||||
|
@ -1300,6 +1300,10 @@ void process_uxst_session(struct task *t, struct timeval *next)
|
|||||||
} while (fsm_resync);
|
} while (fsm_resync);
|
||||||
|
|
||||||
if (likely(s->cli_state != CL_STCLOSE || s->srv_state != SV_STCLOSE)) {
|
if (likely(s->cli_state != CL_STCLOSE || s->srv_state != SV_STCLOSE)) {
|
||||||
|
|
||||||
|
if ((s->fe->options & PR_O_CONTSTATS) && (s->flags & SN_BE_ASSIGNED))
|
||||||
|
session_process_counters(s);
|
||||||
|
|
||||||
s->req->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
|
s->req->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
|
||||||
s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
|
s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
|
||||||
|
|
||||||
@ -1332,23 +1336,7 @@ void process_uxst_session(struct task *t, struct timeval *next)
|
|||||||
}
|
}
|
||||||
|
|
||||||
s->logs.t_close = tv_ms_elapsed(&s->logs.tv_accept, &now);
|
s->logs.t_close = tv_ms_elapsed(&s->logs.tv_accept, &now);
|
||||||
if (s->req != NULL)
|
session_process_counters(s);
|
||||||
s->logs.bytes_in = s->req->total;
|
|
||||||
if (s->rep != NULL)
|
|
||||||
s->logs.bytes_out = s->rep->total;
|
|
||||||
|
|
||||||
if (s->fe) {
|
|
||||||
s->fe->bytes_in += s->logs.bytes_in;
|
|
||||||
s->fe->bytes_out += s->logs.bytes_out;
|
|
||||||
}
|
|
||||||
if (s->be && (s->be != s->fe)) {
|
|
||||||
s->be->bytes_in += s->logs.bytes_in;
|
|
||||||
s->be->bytes_out += s->logs.bytes_out;
|
|
||||||
}
|
|
||||||
if (s->srv) {
|
|
||||||
s->srv->bytes_in += s->logs.bytes_in;
|
|
||||||
s->srv->bytes_out += s->logs.bytes_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* let's do a final log if we need it */
|
/* let's do a final log if we need it */
|
||||||
if (s->logs.logwait &&
|
if (s->logs.logwait &&
|
||||||
|
@ -102,6 +102,38 @@ int init_session()
|
|||||||
return pool2_session != NULL;
|
return pool2_session != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void session_process_counters(struct session *s) {
|
||||||
|
|
||||||
|
unsigned long long bytes;
|
||||||
|
|
||||||
|
if (s->req && s->req->total != s->logs.bytes_in) {
|
||||||
|
bytes = s->req->total - s->logs.bytes_in;
|
||||||
|
|
||||||
|
s->fe->bytes_in += bytes;
|
||||||
|
|
||||||
|
if (s->be != s->fe)
|
||||||
|
s->be->bytes_in += bytes;
|
||||||
|
|
||||||
|
if (s->srv)
|
||||||
|
s->srv->bytes_in += bytes;
|
||||||
|
|
||||||
|
s->logs.bytes_in = s->req->total;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->rep && s->rep->total != s->logs.bytes_out) {
|
||||||
|
bytes = s->rep->total - s->logs.bytes_out;
|
||||||
|
|
||||||
|
s->fe->bytes_out += bytes;
|
||||||
|
|
||||||
|
if (s->be != s->fe)
|
||||||
|
s->be->bytes_out += bytes;
|
||||||
|
|
||||||
|
if (s->srv)
|
||||||
|
s->srv->bytes_out += bytes;
|
||||||
|
|
||||||
|
s->logs.bytes_out = s->rep->total;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Local variables:
|
* Local variables:
|
||||||
|
Loading…
Reference in New Issue
Block a user