From 74fa7fbec947f04f2245500d44903fba6092d711 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Fri, 23 Nov 2012 14:43:49 +0100 Subject: [PATCH] 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. --- src/checks.c | 85 +++++++++++++++++++++++----------------------------- 1 file changed, 38 insertions(+), 47 deletions(-) diff --git a/src/checks.c b/src/checks.c index 5d1c1187b..352e19f53 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 */ - /* 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)) - set_server_enabled(s); - else if (!(s->state & SRV_GOINGDOWN) && - ((s->result & (SRV_CHK_PASSED | SRV_CHK_DISABLE)) == - (SRV_CHK_PASSED | SRV_CHK_DISABLE))) - set_server_disabled(s); - } + /* check complete or aborted */ - 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->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); - - 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))); + } + 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_DISABLE)) + set_server_enabled(s); + 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); } - 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; + 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)); } reschedule: while (tick_is_expired(t->expire, now_ms)) t->expire = tick_add(t->expire, MS_TO_TICKS(s->inter)); + out_wait: return t; }