]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] listeners: queue proxy-bound listeners at the proxy's
authorWilly Tarreau <w@1wt.eu>
Sun, 24 Jul 2011 21:55:06 +0000 (23:55 +0200)
committerWilly Tarreau <w@1wt.eu>
Sun, 24 Jul 2011 21:55:06 +0000 (23:55 +0200)
All listeners that are limited by a proxy-specific resource are now
queued at the proxy's and not globally. This allows finer-grained
wakeups when releasing resource.

include/types/proxy.h
src/cfgparse.c
src/proxy.c
src/session.c
src/stream_sock.c

index fea8a5ea38a16ed41665ce2172255c9e79431c11..9bda57838a57e54ebbae9a2ec78645e331056d93 100644 (file)
@@ -301,6 +301,7 @@ struct proxy {
        struct pxcounters be_counters;          /* backend statistics counters */
        struct pxcounters fe_counters;          /* frontend statistics counters */
 
+       struct list listener_queue;             /* list of the temporarily limited listeners because of lack of a proxy resource */
        struct stktable table;                  /* table for storing sticking sessions */
 
        int grace;                              /* grace time after stop request */
index 6e38962d2a5d91a63cab4f700c09bb13c80a9eb5..21ef3d995fe8fd87bb0e62ba31560a3200400339 100644 (file)
@@ -1041,6 +1041,7 @@ static void init_new_proxy(struct proxy *p)
        LIST_INIT(&p->tcp_req.l4_rules);
        LIST_INIT(&p->req_add);
        LIST_INIT(&p->rsp_add);
+       LIST_INIT(&p->listener_queue);
 
        /* Timeouts are defined as -1 */
        proxy_reset_timeouts(p);
index 2184a1bcb0b9ae87fc9809014f3f817563f62f7d..25398a966bc59cf3913450ed6266086d43767fab 100644 (file)
@@ -499,6 +499,10 @@ void maintain_proxies(int *next)
                                goto do_block;
                        }
 
+                       /* The proxy is not limited so we can re-enable any waiting listener */
+                       if (!LIST_ISEMPTY(&p->listener_queue))
+                               dequeue_all_listeners(&p->listener_queue);
+
                        /* OK we have no reason to block, so let's unblock if we were blocking */
                        if (p->state == PR_STIDLE) {
                                for (l = p->listen; l != NULL; l = l->next)
index 750cf402312ab2f2c364991eb4feb37c6cf56867..65c92db0d1f0f3142e7b511258074e7d0475253b 100644 (file)
@@ -2096,6 +2096,9 @@ struct task *process_session(struct task *t)
        if (!LIST_ISEMPTY(&global_listener_queue))
                dequeue_all_listeners(&global_listener_queue);
 
+       if (!LIST_ISEMPTY(&s->fe->listener_queue))
+               dequeue_all_listeners(&s->fe->listener_queue);
+
        if (unlikely((global.mode & MODE_DEBUG) &&
                     (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)))) {
                int len;
index fa03a625b1e2d7fa357671c0e455203db491d5e6..a0b2c111447499919370f9735b46f2ef93cdced3 100644 (file)
@@ -1192,7 +1192,6 @@ int stream_sock_accept(int fd)
        int max_accept = global.tune.maxaccept;
        int cfd;
        int ret;
-       int loops = 0;
 
        if (unlikely(l->nbconn >= l->maxconn)) {
                listener_full(l);
@@ -1201,15 +1200,31 @@ int stream_sock_accept(int fd)
 
        if (p && p->fe_sps_lim) {
                int max = freq_ctr_remain(&p->fe_sess_per_sec, p->fe_sps_lim, 0);
+
+               if (unlikely(!max)) {
+                       /* frontend accept rate limit was reached */
+                       limit_listener(l, &p->listener_queue);
+                       return 0;
+               }
+
                if (max_accept > max)
                        max_accept = max;
        }
 
-       while ((!p || p->feconn < p->maxconn) && actconn < global.maxconn && max_accept--) {
+       while (max_accept--) {
                struct sockaddr_storage addr;
                socklen_t laddr = sizeof(addr);
 
-               loops++;
+               if (unlikely(actconn >= global.maxconn)) {
+                       limit_listener(l, &global_listener_queue);
+                       return 0;
+               }
+
+               if (unlikely(p && p->feconn >= p->maxconn)) {
+                       limit_listener(l, &p->listener_queue);
+                       return 0;
+               }
+
                cfd = accept(fd, (struct sockaddr *)&addr, &laddr);
                if (unlikely(cfd == -1)) {
                        switch (errno) {
@@ -1287,10 +1302,6 @@ int stream_sock_accept(int fd)
 
        } /* end of while (p->feconn < p->maxconn) */
 
-       /* if we did not even enter the loop, we've reached resource limits */
-       if (!loops && max_accept)
-               limit_listener(l, &global_listener_queue);
-
        return 0;
 }