]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
Revert "implemented the weighted load balancing based on a server map."
authorwilly tarreau <willy@wtap.(none)>
Sat, 15 Apr 2006 19:10:27 +0000 (21:10 +0200)
committerwilly tarreau <willy@wtap.(none)>
Sat, 15 Apr 2006 19:10:27 +0000 (21:10 +0200)
This reverts e0fa4965762fad998f214e30ec8f85b04e83130e commit.

haproxy.c

index b8cc48d0e4aa9fbe2a12715652f60fd4c4e813bc..81e793475bbb81d9e07fce1b4ba69a1fa1208c5a 100644 (file)
--- a/haproxy.c
+++ b/haproxy.c
@@ -514,7 +514,7 @@ struct server {
     int cur_sess;                      /* number of currently active sessions (including syn_sent) */
     unsigned int cum_sess;             /* cumulated number of sessions really sent to this server */
     unsigned char uweight, eweight;    /* user-specified weight-1, and effective weight-1 */
-    unsigned int wscore;               /* weight score, used during srv map computation */
+    unsigned short wsquare;            /* eweight*eweight, to speed up map computation */
     struct proxy *proxy;               /* the proxy this server belongs to */
 };
 
@@ -581,12 +581,8 @@ struct proxy {
     struct in_addr mon_net, mon_mask;  /* don't forward connections from this net (network order) FIXME: should support IPv6 */
     int state;                         /* proxy state */
     struct sockaddr_in dispatch_addr;  /* the default address to connect to */
-    struct server *srv;                        /* known servers */
-    int srv_act, srv_bck;              /* # of running servers */
-    int tot_wact, tot_wbck;            /* total weights of active and backup servers */
-    struct server **srv_map;           /* the server map used to apply weights */
-    int srv_map_sz;                    /* the size of the effective server map */
-    int srv_rr_idx;                    /* next server to be elected in round robin mode */
+    struct server *srv, *cursrv;       /* known servers, current server */
+    int srv_act, srv_bck;              /* # of servers */
     char *cookie_name;                 /* name of the cookie to look for */
     int  cookie_len;                   /* strlen(cookie_name), computed only once */
     char *appsession_name;             /* name of the cookie to look for */
@@ -1816,101 +1812,77 @@ static inline void session_free(struct session *s) {
 /*
  * This function recounts the number of usable active and backup servers for
  * proxy <p>. These numbers are returned into the p->srv_act and p->srv_bck.
- * This function also recomputes the total active and backup weights.
  */
-static void recount_servers(struct proxy *px) {
+static inline void recount_servers(struct proxy *px) {
     struct server *srv;
 
-    px->srv_act = 0; px->srv_bck = px->tot_wact = px->tot_wbck = 0;
+    px->srv_act = 0; px->srv_bck = 0;
     for (srv = px->srv; srv != NULL; srv = srv->next) {
         if (srv->state & SRV_RUNNING) {
-            if (srv->state & SRV_BACKUP) {
+            if (srv->state & SRV_BACKUP)
                 px->srv_bck++;
-                px->tot_wbck += srv->eweight + 1;
-            } else {
+            else
                 px->srv_act++;
-                px->tot_wact += srv->eweight + 1;
-            }
         }
     }
 }
 
-/* This function recomputes the server map for proxy px. It
- * relies on px->tot_wact and px->tot_wbck, so it must be
- * called after recount_servers(). It also expects px->srv_map
- * to be initialized to the largest value needed.
- */
-static void recalc_server_map(struct proxy *px) {
-    int o, tot, flag;
-    struct server *cur, *best;
-
-    if (px->srv_act) {
-       flag = SRV_RUNNING;
-       tot  = px->tot_wact;
-    } else if (px->srv_bck) {
-       flag = SRV_RUNNING | SRV_BACKUP;
-       if (px->options & PR_O_USE_ALL_BK)
-           tot = px->tot_wbck;
-       else
-           tot = 1; /* the first server is enough */
-    } else {
-       px->srv_map_sz = 0;
-       return;
-    }
-
-    /* this algorithm gives priority to the first server, which means that
-     * it will respect the declaration order for equivalent weights, and
-     * that whatever the weights, the first server called will always be
-     * the first declard. This is an important asumption for the backup
-     * case, where we want the first server only.
-     */
-    for (cur = px->srv; cur; cur = cur->next)
-       cur->wscore = 0;
-
-    for (o = 0; o < tot; o++) {
-       int max = 0;
-       best = NULL;
-       for (cur = px->srv; cur; cur = cur->next) {
-           if ((cur->state & (SRV_RUNNING | SRV_BACKUP)) == flag) {
-               int v;
-
-               /* If we are forced to return only one server, we don't want to
-                * go further, because we would return the wrong one due to
-                * divide overflow.
-                */
-               if (tot == 1) {
-                   best = cur;
-                   break;
-               }
-
-               cur->wscore += cur->eweight + 1;
-               v = (cur->wscore + tot) / tot; /* result between 0 and 3 */
-               if (best == NULL || v > max) {
-                   max = v;
-                   best = cur;
-               }
-           }
-       }
-       px->srv_map[o] = best;
-       best->wscore -= tot;
-    }
-    px->srv_map_sz = tot;
-}
-
 /*
  * This function tries to find a running server for the proxy <px> following
  * the round-robin method. Depending on the number of active/backup servers,
  * it will either look for active servers, or for backup servers.
- * If any server is found, it will be returned and px->srv_rr_idx will be updated
+ * If any server is found, it will be returned and px->cursrv will be updated
  * to point to the next server. If no valid server is found, NULL is returned.
  */
 static inline struct server *get_server_rr(struct proxy *px) {
-    if (px->srv_map_sz == 0)
-       return NULL;
+    struct server *srv;
+    struct server *end;
+
+    if (px->srv_act) {
+        srv = px->cursrv;
+       if (srv == NULL)
+           srv = px->srv;
+        end = srv;
+       do  {
+           if ((srv->state & (SRV_RUNNING | SRV_BACKUP)) == SRV_RUNNING) {
+                px->cursrv = srv->next;
+               return srv;
+            }
+
+           srv = srv->next;
+           if (srv == NULL)
+               srv = px->srv;
+       } while (srv != end);
+        /* note that theorically we should not get there */
+    }
 
-    if (px->srv_rr_idx < 0 || px->srv_rr_idx >= px->srv_map_sz)
-       px->srv_rr_idx = 0;
-    return px->srv_map[px->srv_rr_idx++];
+    if (px->srv_bck) {
+       /* By default, we look for the first backup server if all others are
+        * DOWN. But in some cases, it may be desirable to load-balance across
+        * all backup servers.
+        */
+        if (px->options & PR_O_USE_ALL_BK)
+            srv = px->cursrv;
+        else
+            srv = px->srv;
+
+       if (srv == NULL)
+           srv = px->srv;
+        end = srv;
+       do  {
+           if (srv->state & SRV_RUNNING) {
+                px->cursrv = srv->next;
+               return srv;
+            }
+           srv = srv->next;
+           if (srv == NULL)
+               srv = px->srv;
+       } while (srv != end);
+        /* note that theorically we should not get there */
+    }
+
+    /* if we get there, it means there are no available servers at all */
+    return NULL;
 }
 
 
@@ -1922,20 +1894,58 @@ static inline struct server *get_server_rr(struct proxy *px) {
  * NULL is returned.
  */
 static inline struct server *get_server_sh(struct proxy *px, char *addr, int len) {
-    unsigned int h, l;
+    struct server *srv;
 
-    if (px->srv_map_sz == 0)
-       return NULL;
+    if (px->srv_act) {
+        unsigned int h, l;
 
-    l = h = 0;
-    if (px->srv_act > 1) {
-       while ((l + sizeof (int)) <= len) {
-           h ^= ntohl(*(unsigned int *)(&addr[l]));
-           l += sizeof (int);
+        l = h = 0;
+        if (px->srv_act > 1) {
+            while ((l + sizeof (int)) <= len) {
+                h ^= ntohl(*(unsigned int *)(&addr[l]));
+                l += sizeof (int);
+            }
+            h %= px->srv_act;
+        }
+
+        for (srv = px->srv; srv; srv = srv->next) {
+           if ((srv->state & (SRV_RUNNING | SRV_BACKUP)) == SRV_RUNNING) {
+                if (!h)
+                    return srv;
+                h--;
+            }
+       }
+        /* note that theorically we should not get there */
+    }
+
+    if (px->srv_bck) {
+        unsigned int h, l;
+
+       /* By default, we look for the first backup server if all others are
+        * DOWN. But in some cases, it may be desirable to load-balance across
+        * all backup servers.
+        */
+        l = h = 0;
+        if (px->srv_bck > 1 && px->options & PR_O_USE_ALL_BK) {
+            while ((l + sizeof (int)) <= len) {
+                h ^= ntohl(*(unsigned int *)(&addr[l]));
+                l += sizeof (int);
+            }
+            h %= px->srv_bck;
+        }
+
+        for (srv = px->srv; srv; srv = srv->next) {
+           if (srv->state & SRV_RUNNING) {
+                if (!h)
+                    return srv;
+                h--;
+            }
        }
-       h %= px->srv_map_sz;
+        /* note that theorically we should not get there */
     }
-    return px->srv_map[h];
+
+    /* if we get there, it means there are no available servers at all */
+    return NULL;
 }
 
 
@@ -5332,7 +5342,6 @@ int process_chk(struct task *t) {
            s->state &= ~SRV_RUNNING;
            if (s->health == s->rise) {
                 recount_servers(s->proxy);
-               recalc_server_map(s->proxy);
                Warning("%sServer %s/%s DOWN. %d active and %d backup servers left.%s\n",
                         s->state & SRV_BACKUP ? "Backup " : "",
                         s->proxy->id, s->id, s->proxy->srv_act, s->proxy->srv_bck,
@@ -5368,7 +5377,6 @@ int process_chk(struct task *t) {
 
                if (s->health == s->rise) {
                     recount_servers(s->proxy);
-                   recalc_server_map(s->proxy);
                    Warning("%sServer %s/%s UP. %d active and %d backup servers online.%s\n",
                             s->state & SRV_BACKUP ? "Backup " : "",
                             s->proxy->id, s->id, s->proxy->srv_act, s->proxy->srv_bck,
@@ -5399,7 +5407,6 @@ int process_chk(struct task *t) {
 
                 if (s->health == s->rise) {
                     recount_servers(s->proxy);
-                   recalc_server_map(s->proxy);
                     Warning("%sServer %s/%s DOWN. %d active and %d backup servers left.%s\n",
                             s->state & SRV_BACKUP ? "Backup " : "",
                             s->proxy->id, s->id, s->proxy->srv_act, s->proxy->srv_bck,
@@ -7016,9 +7023,13 @@ int cfg_parse_listen(char *file, int linenum, char **args) {
            return -1;
        }
 
-       /* the servers are linked backwards first */
-       newsrv->next = curproxy->srv;
-       curproxy->srv = newsrv;
+       if (curproxy->srv == NULL)
+           curproxy->srv = newsrv;
+       else
+           curproxy->cursrv->next = newsrv;
+       curproxy->cursrv = newsrv;
+
+       newsrv->next = NULL;
        newsrv->proxy = curproxy;
 
        do_check = 0;
@@ -7832,6 +7843,7 @@ int readcfgfile(char *file) {
     }
 
     while (curproxy != NULL) {
+       curproxy->cursrv = NULL;
        if (curproxy->state == PR_STSTOPPED) {
            curproxy = curproxy->next;
            continue;
@@ -7888,59 +7900,29 @@ int readcfgfile(char *file) {
                      file, curproxy->id);
                cfgerr++;
            }
-       }
-
-       /* first, we will invert the servers list order */
-       newsrv = NULL;
-       while (curproxy->srv) {
-           struct server *next;
-
-           next = curproxy->srv->next;
-           curproxy->srv->next = newsrv;
-           newsrv = curproxy->srv;
-           if (!next)
-               break;
-           curproxy->srv = next;
-       }
-
-       /* now, newsrv == curproxy->srv */
-       if (newsrv) {
-           struct server *srv;
-           int pgcd;
-           int act, bck;
+           else {
+               struct server *srv;
+               int pgcd;
 
-           /* We will factor the weights to reduce the table,
-            * using Euclide's largest common divisor algorithm
-            */
-           pgcd = newsrv->uweight + 1;
-           for (srv = newsrv->next; srv && pgcd > 1; srv = srv->next) {
-               int t, w;
-               
-               w = srv->uweight + 1;
-               while (w) {
-                   t = pgcd % w;
-                   pgcd = w;
-                   w = t;
+               if (newsrv) {
+                   /* We will factor the weights to reduce the table,
+                    * using Euclide's largest common divisor algorithm
+                    */
+                   pgcd = newsrv->uweight + 1;
+                   for (srv = newsrv->next; srv && pgcd > 1; srv = srv->next) {
+                       int t, w;
+
+                       w = srv->uweight + 1;
+                       while (w) {
+                           t = pgcd % w;
+                           pgcd = w;
+                           w = t;
                        }
+                   }
+                   for (srv = newsrv; srv; srv = srv->next)
+                       srv->eweight = ((srv->uweight + 1) / pgcd) - 1;
+               }
            }
-
-           act = bck = 0;
-           for (srv = newsrv; srv; srv = srv->next) {
-               srv->eweight = ((srv->uweight + 1) / pgcd) - 1;
-               if (srv->state & SRV_BACKUP)
-                   bck += srv->eweight + 1;
-               else
-                   act += srv->eweight + 1;
-           }
-
-           /* this is the largest map we will ever need for this servers list */
-           if (act < bck)
-               act = bck;
-
-           curproxy->srv_map = (struct server **)calloc(act, sizeof(struct server *));
-           /* recounts servers and their weights */
-           recount_servers(curproxy);
-           recalc_server_map(curproxy);
        }
 
        if (curproxy->options & PR_O_LOGASAP)