From: Willy Tarreau Date: Fri, 23 Nov 2012 13:43:49 +0000 (+0100) Subject: MEDIUM: checks: close the socket as soon as we have a response X-Git-Tag: v1.5-dev14~25 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=74fa7fbec947f04f2245500d44903fba6092d711;p=thirdparty%2Fhaproxy.git MEDIUM: checks: close the socket as soon as we have a response Until now, the check socked was closed in the task which handles the check, which can sometimes be substantially later when many tasks are running. It's much cleaner to close() in the wake call, which also helps removing some FD management from the task itself. The code is faster and smaller, and fast health checks show a more predictable behaviour. --- diff --git a/src/checks.c b/src/checks.c index 5d1c1187b0..352e19f536 100644 --- a/src/checks.c +++ b/src/checks.c @@ -1184,6 +1184,12 @@ static int wake_srv_chk(struct connection *conn) if (unlikely(conn->flags & CO_FL_ERROR)) task_wakeup(s->check.task, TASK_WOKEN_IO); + if (s->result & (SRV_CHK_FAILED|SRV_CHK_PASSED)) { + conn_xprt_close(conn); + if (conn->ctrl) + fd_delete(conn->t.sock.fd); + conn->ctrl = NULL; + } return 0; } @@ -1390,82 +1396,67 @@ static struct task *process_chk(struct task *t) else if (expired) set_server_check_status(s, HCHK_STATUS_L6TOUT, NULL); } - else if ((conn->flags & CO_FL_CONNECTED) && !(s->proxy->options2 & PR_O2_CHK_ANY)) { + else if (!(s->proxy->options2 & PR_O2_CHK_ANY)) { /* good connection is enough for pure TCP check */ if (s->check.use_ssl) set_server_check_status(s, HCHK_STATUS_L6OK, NULL); else set_server_check_status(s, HCHK_STATUS_L4OK, NULL); } - else if ((conn->flags & CO_FL_CONNECTED) && expired) { + else if (expired) { /* connection established but expired check */ if ((s->proxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) set_server_check_status(s, HCHK_STATUS_L6TOUT, NULL); else /* HTTP, SMTP, ... */ set_server_check_status(s, HCHK_STATUS_L7TOUT, NULL); + + conn_xprt_close(conn); + if (conn->ctrl) + fd_delete(conn->t.sock.fd); + conn->ctrl = NULL; } + else + goto out_wait; /* timeout not reached, wait again */ } - if ((s->result & (SRV_CHK_FAILED|SRV_CHK_PASSED)) == SRV_CHK_PASSED) { /* good server detected */ + /* check complete or aborted */ + + if (s->result & SRV_CHK_FAILED) { /* a failure or timeout detected */ + if (s->health > s->rise) { + s->health--; /* still good */ + s->counters.failed_checks++; + } + else + set_server_down(s); + } + else { /* check was OK */ /* we may have to add/remove this server from the LB group */ if ((s->state & SRV_RUNNING) && (s->proxy->options & PR_O_DISABLE404)) { - if ((s->state & SRV_GOINGDOWN) && - ((s->result & (SRV_CHK_PASSED|SRV_CHK_DISABLE)) == SRV_CHK_PASSED)) + if ((s->state & SRV_GOINGDOWN) && !(s->result & SRV_CHK_DISABLE)) set_server_enabled(s); - else if (!(s->state & SRV_GOINGDOWN) && - ((s->result & (SRV_CHK_PASSED | SRV_CHK_DISABLE)) == - (SRV_CHK_PASSED | SRV_CHK_DISABLE))) + else if (!(s->state & SRV_GOINGDOWN) && (s->result & SRV_CHK_DISABLE)) set_server_disabled(s); } if (s->health < s->rise + s->fall - 1) { s->health++; /* was bad, stays for a while */ - set_server_up(s); } - - s->state &= ~SRV_CHK_RUNNING; - conn_xprt_close(conn); - if (conn->ctrl) - fd_delete(conn->t.sock.fd); - - rv = 0; - if (global.spread_checks > 0) { - rv = srv_getinter(s) * global.spread_checks / 100; - rv -= (int) (2 * rv * (rand() / (RAND_MAX + 1.0))); - } - t->expire = tick_add(now_ms, MS_TO_TICKS(srv_getinter(s) + rv)); } - else if (s->result & SRV_CHK_FAILED) { - /* failure or timeout detected */ - if (s->health > s->rise) { - s->health--; /* still good */ - s->counters.failed_checks++; - } - else - set_server_down(s); - - s->state &= ~SRV_CHK_RUNNING; - conn_xprt_close(conn); - if (conn->ctrl) - fd_delete(conn->t.sock.fd); + s->state &= ~SRV_CHK_RUNNING; - rv = 0; - if (global.spread_checks > 0) { - rv = srv_getinter(s) * global.spread_checks / 100; - rv -= (int) (2 * rv * (rand() / (RAND_MAX + 1.0))); - } - t->expire = tick_add(now_ms, MS_TO_TICKS(srv_getinter(s) + rv)); - } - else { - /* if result is unknown and there's no timeout, we have to wait again */ - s->result = SRV_CHK_UNKNOWN; + rv = 0; + if (global.spread_checks > 0) { + rv = srv_getinter(s) * global.spread_checks / 100; + rv -= (int) (2 * rv * (rand() / (RAND_MAX + 1.0))); } + t->expire = tick_add(now_ms, MS_TO_TICKS(srv_getinter(s) + rv)); } reschedule: while (tick_is_expired(t->expire, now_ms)) t->expire = tick_add(t->expire, MS_TO_TICKS(s->inter)); + out_wait: return t; }