]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: checks: close the socket as soon as we have a response
authorWilly Tarreau <w@1wt.eu>
Fri, 23 Nov 2012 13:43:49 +0000 (14:43 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 23 Nov 2012 13:43:49 +0000 (14:43 +0100)
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

index 5d1c1187b0cc2a9efb24342d67ae267efcff82b9..352e19f5364aae3a283b64f820c3aaa2433464ec 100644 (file)
@@ -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;
 }