From f1221aa19ff64d0702df0fa1af0808cfa019e435 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sun, 17 Dec 2006 22:14:12 +0100 Subject: [PATCH] [MEDIUM] separated nbconn into feconn and beconn The nbconn attribute in the proxies was not relevant anymore because a frontend A may use backend B and both of them must account for their respective connections. For this reason, there now are two separate counters for frontend and backend connections. The stats page has been updated to reflect the backend, but a separate line entry for the frontend with error counts would be good. Note that as of now, beconn may be higher than maxconn, because maxconn applies to the frontend, while beconn may be increased due to sessions passed from another frontend. --- include/types/proxy.h | 5 +++-- include/types/session.h | 2 +- src/client.c | 12 +++++------ src/haproxy.c | 8 +++---- src/log.c | 4 ++-- src/proto_http.c | 47 +++++++++++++++++++++++++++++++++-------- src/proxy.c | 4 ++-- src/queue.c | 8 ++++--- 8 files changed, 61 insertions(+), 29 deletions(-) diff --git a/include/types/proxy.h b/include/types/proxy.h index 9e6f42123..a82f195c2 100644 --- a/include/types/proxy.h +++ b/include/types/proxy.h @@ -94,8 +94,9 @@ struct proxy { struct list pendconns; /* pending connections with no server assigned yet */ int nbpend, nbpend_max; /* number of pending connections with no server assigned yet */ int totpend; /* total number of pending connections on this instance (for stats) */ - unsigned int nbconn, nbconn_max; /* # of active sessions */ - unsigned int cum_conn; /* cumulated number of processed sessions */ + unsigned int feconn, feconn_max; /* # of active frontend sessions */ + unsigned int beconn, beconn_max; /* # of active backend sessions */ + unsigned int cum_feconn, cum_beconn; /* cumulated number of processed sessions */ unsigned int maxconn; /* max # of active sessions */ unsigned failed_conns, failed_resp; /* failed connect() and responses */ unsigned failed_secu; /* blocked responses because of security concerns */ diff --git a/include/types/session.h b/include/types/session.h index 2b3d70529..3800b4b5e 100644 --- a/include/types/session.h +++ b/include/types/session.h @@ -45,7 +45,7 @@ #define SN_CLALLOW 0x00000004 /* a client header matches an allow regex */ #define SN_SVDENY 0x00000008 /* a server header matches a deny regex */ #define SN_SVALLOW 0x00000010 /* a server header matches an allow regex */ -#define SN_UNUSED_1 0x00000020 /* unused bit */ +#define SN_BE_ASSIGNED 0x00000020 /* a backend was assigned. Conns are accounted. */ /* session flags dedicated to cookies : bits values 0x40, 0x80 (0-3 shift 6) */ #define SN_CK_NONE 0x00000000 /* this session had no cookie */ diff --git a/src/client.c b/src/client.c index e55f20bba..2e2aaff47 100644 --- a/src/client.c +++ b/src/client.c @@ -65,7 +65,7 @@ int event_accept(int fd) { else max_accept = -1; - while (p->nbconn < p->maxconn && max_accept--) { + while (p->feconn < p->maxconn && max_accept--) { struct sockaddr_storage addr; socklen_t laddr = sizeof(addr); @@ -191,7 +191,7 @@ int event_accept(int fd) { s->data_source = DATA_SRC_NONE; s->uniq_id = totalconn; - p->cum_conn++; + p->cum_feconn++; /* cum_beconn will be increased once assigned */ s->rsp_cap = NULL; s->hreq.cap = NULL; @@ -415,14 +415,14 @@ int event_accept(int fd) { if (p->mode != PR_MODE_HEALTH) task_wakeup(&rq, t); - p->nbconn++; - if (p->nbconn > p->nbconn_max) - p->nbconn_max = p->nbconn; + p->feconn++; /* beconn will be increased later */ + if (p->feconn > p->feconn_max) + p->feconn_max = p->feconn; actconn++; totalconn++; // fprintf(stderr, "accepting from %p => %d conn, %d total, task=%p\n", p, actconn, totalconn, t); - } /* end of while (p->nbconn < p->maxconn) */ + } /* end of while (p->feconn < p->maxconn) */ return 0; } diff --git a/src/haproxy.c b/src/haproxy.c index 145954385..d2b6d10ad 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -233,16 +233,16 @@ void sig_dump_state(int sig) if (p->srv_act == 0) { snprintf(trash, sizeof(trash), - "SIGHUP: Proxy %s %s ! Conn: %d act, %d pend (%d unass), %d tot.", + "SIGHUP: Proxy %s %s ! Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %d+%d.", p->id, (p->srv_bck) ? "is running on backup servers" : "has no server available", - p->nbconn, p->totpend, p->nbpend, p->cum_conn); + p->feconn, p->beconn, p->totpend, p->nbpend, p->cum_feconn, p->cum_beconn); } else { snprintf(trash, sizeof(trash), "SIGHUP: Proxy %s has %d active servers and %d backup servers available." - " Conn: %d act, %d pend (%d unass), %d tot.", + " Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %d+%d.", p->id, p->srv_act, p->srv_bck, - p->nbconn, p->totpend, p->nbpend, p->cum_conn); + p->feconn, p->beconn, p->totpend, p->nbpend, p->cum_feconn, p->cum_beconn); } Warning("%s\n", trash); send_log(p, LOG_NOTICE, "%s\n", trash); diff --git a/src/log.c b/src/log.c index 077335811..1c925968f 100644 --- a/src/log.c +++ b/src/log.c @@ -386,7 +386,7 @@ void sess_log(struct session *s) sess_fin_state[(s->flags & SN_FINST_MASK) >> SN_FINST_SHIFT], (p->options & PR_O_COOK_ANY) ? sess_cookie[(s->flags & SN_CK_MASK) >> SN_CK_SHIFT] : '-', (p->options & PR_O_COOK_ANY) ? sess_set_cookie[(s->flags & SN_SCK_MASK) >> SN_SCK_SHIFT] : '-', - s->srv ? s->srv->cur_sess : 0, p->nbconn, actconn, + s->srv ? s->srv->cur_sess : 0, p->beconn, actconn, s->logs.srv_queue_size, s->logs.prx_queue_size, tmpline); } else { @@ -406,7 +406,7 @@ void sess_log(struct session *s) (p->to_log & LW_BYTES) ? "" : "+", s->logs.bytes, sess_term_cond[(s->flags & SN_ERR_MASK) >> SN_ERR_SHIFT], sess_fin_state[(s->flags & SN_FINST_MASK) >> SN_FINST_SHIFT], - s->srv ? s->srv->cur_sess : 0, p->nbconn, actconn, + s->srv ? s->srv->cur_sess : 0, p->beconn, actconn, s->logs.srv_queue_size, s->logs.prx_queue_size); } diff --git a/src/proto_http.c b/src/proto_http.c index e87da3ec3..8ee2cf864 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -258,7 +258,9 @@ int process_session(struct task *t) return tv_remain2(&now, &t->expire); /* nothing more to do */ } - s->fe->nbconn--; + s->fe->feconn--; + if (s->flags & SN_BE_ASSIGNED) + s->be->beprm->beconn--; actconn--; if ((global.mode & MODE_DEBUG) && (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) { @@ -917,6 +919,18 @@ int process_cli(struct session *t) t->hreq.meth = find_http_meth(t->hreq.start.str, t->hreq.start.len); } + if (!(t->flags & SN_BE_ASSIGNED) && (t->be != cur_proxy)) { + /* to ensure correct connection accounting on + * the backend, we count the connection for the + * one managing the queue. + */ + t->be->beprm->beconn++; + if (t->be->beprm->beconn > t->be->beprm->beconn_max) + t->be->beprm->beconn_max = t->be->beprm->beconn; + t->be->beprm->cum_beconn++; + t->flags |= SN_BE_ASSIGNED; + } + /* has the request been denied ? */ if (t->flags & SN_CLDENY) { /* no need to go further */ @@ -949,6 +963,19 @@ int process_cli(struct session *t) } while (cur_proxy != t->be); /* we loop only if t->be has changed */ + if (!(t->flags & SN_BE_ASSIGNED)) { + /* To ensure correct connection accounting on + * the backend, we count the connection for the + * one managing the queue. + */ + t->be->beprm->beconn++; + if (t->be->beprm->beconn > t->be->beprm->beconn_max) + t->be->beprm->beconn_max = t->be->beprm->beconn; + t->be->beprm->cum_beconn++; + t->flags |= SN_BE_ASSIGNED; + } + + /* * Right now, we know that we have processed the entire headers * and that unwanted requests have been filtered out. We can do @@ -2748,10 +2775,12 @@ int produce_content(struct session *s) msglen += snprintf(trash + msglen, sizeof(trash) - msglen, "

> Proxy instance %s : " - "%d conns (maxconn=%d), %d queued (%d unassigned), %d total conns

\n" + "%d front conns (max=%d), %d back, " + "%d queued (%d unassigned), %d total front conns, %d back\n" "", px->id, - px->nbconn, px->maxconn, px->totpend, px->nbpend, px->cum_conn); + px->feconn, px->maxconn, px->beconn, + px->totpend, px->nbpend, px->cum_feconn, px->cum_beconn); msglen += snprintf(trash + msglen, sizeof(trash) - msglen, "\n" @@ -2853,8 +2882,8 @@ int produce_content(struct session *s) * failed. We cannot count this during the servers dump because it * might be interrupted multiple times. */ - dispatch_sess = px->nbconn; - dispatch_cum = px->cum_conn; + dispatch_sess = px->beconn; + dispatch_cum = px->cum_beconn; failed_secu = px->failed_secu; failed_conns = px->failed_conns; failed_resp = px->failed_resp; @@ -2888,8 +2917,8 @@ int produce_content(struct session *s) /* sessions : current, max, limit, cumul. */ msglen += snprintf(trash + msglen, sizeof(trash) - msglen, - "", - dispatch_sess, px->nbconn_max, px->maxconn, dispatch_cum); + "", + dispatch_sess, px->beconn_max, dispatch_cum); /* errors : connect, response, security */ msglen += snprintf(trash + msglen, sizeof(trash) - msglen, @@ -2917,8 +2946,8 @@ int produce_content(struct session *s) /* sessions : current, max, limit, cumul */ msglen += snprintf(trash + msglen, sizeof(trash) - msglen, - "", - px->nbconn, px->nbconn_max, px->maxconn, px->cum_conn); + "", + px->beconn, px->beconn_max, px->cum_beconn); /* errors : connect, response, security */ msglen += snprintf(trash + msglen, sizeof(trash) - msglen, diff --git a/src/proxy.c b/src/proxy.c index 09770612e..4f1028900 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -161,7 +161,7 @@ int maintain_proxies(void) /* if there are enough free sessions, we'll activate proxies */ if (actconn < global.maxconn) { while (p) { - if (p->nbconn < p->maxconn) { + if (p->feconn < p->maxconn) { if (p->state == PR_STIDLE) { for (l = p->listen; l != NULL; l = l->next) { MY_FD_SET(l->fd, StaticReadEvent); @@ -322,7 +322,7 @@ void listen_proxies(void) for (l = p->listen; l != NULL; l = l->next) { if (listen(l->fd, p->maxconn) == 0) { - if (actconn < global.maxconn && p->nbconn < p->maxconn) { + if (actconn < global.maxconn && p->feconn < p->maxconn) { MY_FD_SET(l->fd, StaticReadEvent); p->state = PR_STRUN; } diff --git a/src/queue.c b/src/queue.c index d672fed00..8f0474cb8 100644 --- a/src/queue.c +++ b/src/queue.c @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -28,9 +29,10 @@ void **pool_pendconn = NULL; */ unsigned int srv_dynamic_maxconn(const struct server *s) { - return s->minconn ? - ((s->maxconn * s->proxy->nbconn / s->proxy->maxconn) < s->minconn) ? s->minconn : - (s->maxconn * s->proxy->nbconn / s->proxy->maxconn) : s->maxconn; + return (s->proxy->beconn >= s->proxy->maxconn) ? s->maxconn : + (s->minconn ? + MAX(s->maxconn * s->proxy->beconn / s->proxy->maxconn, s->minconn) + : s->maxconn); }
%d%d%d%d%d%d-%d%d%d%d%d%d%d-%d