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 */
#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 */
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);
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;
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;
}
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);
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 {
(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);
}
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))) {
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 */
} 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
msglen += snprintf(trash + msglen, sizeof(trash) - msglen,
"<h3>> Proxy instance %s : "
- "%d conns (maxconn=%d), %d queued (%d unassigned), %d total conns</h3>\n"
+ "%d front conns (max=%d), %d back, "
+ "%d queued (%d unassigned), %d total front conns, %d back</h3>\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,
"<table cols=\"16\" class=\"tbl\">\n"
* 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;
/* sessions : current, max, limit, cumul. */
msglen += snprintf(trash + msglen, sizeof(trash) - msglen,
- "<td align=right>%d</td><td align=right>%d</td><td align=right>%d</td><td align=right>%d</td>",
- dispatch_sess, px->nbconn_max, px->maxconn, dispatch_cum);
+ "<td align=right>%d</td><td align=right>%d</td><td align=right>-</td><td align=right>%d</td>",
+ dispatch_sess, px->beconn_max, dispatch_cum);
/* errors : connect, response, security */
msglen += snprintf(trash + msglen, sizeof(trash) - msglen,
/* sessions : current, max, limit, cumul */
msglen += snprintf(trash + msglen, sizeof(trash) - msglen,
- "<td align=right><b>%d</b></td><td align=right><b>%d</b></td><td align=right><b>%d</b></td><td align=right><b>%d</b></td>",
- px->nbconn, px->nbconn_max, px->maxconn, px->cum_conn);
+ "<td align=right><b>%d</b></td><td align=right><b>%d</b></td><td align=right><b>-</b></td><td align=right><b>%d</b></td>",
+ px->beconn, px->beconn_max, px->cum_beconn);
/* errors : connect, response, security */
msglen += snprintf(trash + msglen, sizeof(trash) - msglen,
/* 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);
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;
}
#include <common/config.h>
#include <common/time.h>
+#include <common/tools.h>
#include <types/proxy.h>
#include <types/session.h>
*/
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);
}