|
@@ -2,8 +2,6 @@ package loadbalance
|
|
|
|
|
|
import (
|
|
|
"errors"
|
|
|
- "fmt"
|
|
|
- "log"
|
|
|
"math/rand"
|
|
|
"net/http"
|
|
|
)
|
|
@@ -29,7 +27,7 @@ func (m *RouteManager) GetRequestUpstreamTarget(w http.ResponseWriter, r *http.R
|
|
|
//No valid session found. Assign a new upstream
|
|
|
targetOrigin, index, err := getRandomUpstreamByWeight(origins)
|
|
|
if err != nil {
|
|
|
- fmt.Println("Oops. Unable to get random upstream")
|
|
|
+ m.println("Unable to get random upstream", err)
|
|
|
targetOrigin = origins[0]
|
|
|
index = 0
|
|
|
}
|
|
@@ -44,7 +42,7 @@ func (m *RouteManager) GetRequestUpstreamTarget(w http.ResponseWriter, r *http.R
|
|
|
var err error
|
|
|
targetOrigin, _, err = getRandomUpstreamByWeight(origins)
|
|
|
if err != nil {
|
|
|
- log.Println(err)
|
|
|
+ m.println("Failed to get next origin", err)
|
|
|
targetOrigin = origins[0]
|
|
|
}
|
|
|
|
|
@@ -102,42 +100,66 @@ func (m *RouteManager) getSessionHandler(r *http.Request, upstreams []*Upstream)
|
|
|
/* Functions related to random upstream picking */
|
|
|
// Get a random upstream by the weights defined in Upstream struct, return the upstream, index value and any error
|
|
|
func getRandomUpstreamByWeight(upstreams []*Upstream) (*Upstream, int, error) {
|
|
|
- var ret *Upstream
|
|
|
- sum := 0
|
|
|
- for _, c := range upstreams {
|
|
|
- sum += c.Weight
|
|
|
+ // If there is only one upstream, return it
|
|
|
+ if len(upstreams) == 1 {
|
|
|
+ return upstreams[0], 0, nil
|
|
|
}
|
|
|
- r, err := intRange(0, sum)
|
|
|
- if err != nil {
|
|
|
- return ret, -1, err
|
|
|
+
|
|
|
+ // Preserve the index with upstreams
|
|
|
+ type upstreamWithIndex struct {
|
|
|
+ Upstream *Upstream
|
|
|
+ Index int
|
|
|
}
|
|
|
- counter := 0
|
|
|
- for _, c := range upstreams {
|
|
|
- r -= c.Weight
|
|
|
- if r < 0 {
|
|
|
- return c, counter, nil
|
|
|
+
|
|
|
+ // Calculate total weight for upstreams with weight > 0
|
|
|
+ totalWeight := 0
|
|
|
+ fallbackUpstreams := make([]upstreamWithIndex, 0, len(upstreams))
|
|
|
+
|
|
|
+ for index, upstream := range upstreams {
|
|
|
+ if upstream.Weight > 0 {
|
|
|
+ totalWeight += upstream.Weight
|
|
|
+ } else {
|
|
|
+ // Collect fallback upstreams
|
|
|
+ fallbackUpstreams = append(fallbackUpstreams, upstreamWithIndex{upstream, index})
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // If there are no upstreams with weight > 0, return a fallback upstream if available
|
|
|
+ if totalWeight == 0 {
|
|
|
+ if len(fallbackUpstreams) > 0 {
|
|
|
+ // Randomly select one of the fallback upstreams
|
|
|
+ randIndex := rand.Intn(len(fallbackUpstreams))
|
|
|
+ return fallbackUpstreams[randIndex].Upstream, fallbackUpstreams[randIndex].Index, nil
|
|
|
}
|
|
|
- counter++
|
|
|
+ // No upstreams available at all
|
|
|
+ return nil, -1, errors.New("no valid upstream servers available")
|
|
|
}
|
|
|
|
|
|
- if ret == nil {
|
|
|
- //All fallback
|
|
|
- //use the first one that is with weight = 0
|
|
|
- fallbackUpstreams := []*Upstream{}
|
|
|
- fallbackUpstreamsOriginalID := []int{}
|
|
|
- for ix, upstream := range upstreams {
|
|
|
- if upstream.Weight == 0 {
|
|
|
- fallbackUpstreams = append(fallbackUpstreams, upstream)
|
|
|
- fallbackUpstreamsOriginalID = append(fallbackUpstreamsOriginalID, ix)
|
|
|
+ // Random weight between 0 and total weight
|
|
|
+ randomWeight := rand.Intn(totalWeight)
|
|
|
+
|
|
|
+ // Select an upstream based on the random weight
|
|
|
+ for index, upstream := range upstreams {
|
|
|
+ if upstream.Weight > 0 { // Only consider upstreams with weight > 0
|
|
|
+ if randomWeight < upstream.Weight {
|
|
|
+ // Return the selected upstream and its index
|
|
|
+ return upstream, index, nil
|
|
|
}
|
|
|
+ randomWeight -= upstream.Weight
|
|
|
}
|
|
|
- upstreamID := rand.Intn(len(fallbackUpstreams))
|
|
|
- return fallbackUpstreams[upstreamID], fallbackUpstreamsOriginalID[upstreamID], nil
|
|
|
}
|
|
|
- return ret, -1, errors.New("failed to pick an upstream origin server")
|
|
|
+
|
|
|
+ // If we reach here, it means we should return a fallback upstream if available
|
|
|
+ if len(fallbackUpstreams) > 0 {
|
|
|
+ randIndex := rand.Intn(len(fallbackUpstreams))
|
|
|
+ return fallbackUpstreams[randIndex].Upstream, fallbackUpstreams[randIndex].Index, nil
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil, -1, errors.New("failed to pick an upstream origin server")
|
|
|
}
|
|
|
|
|
|
// IntRange returns a random integer in the range from min to max.
|
|
|
+/*
|
|
|
func intRange(min, max int) (int, error) {
|
|
|
var result int
|
|
|
switch {
|
|
@@ -152,3 +174,4 @@ func intRange(min, max int) (int, error) {
|
|
|
}
|
|
|
return result, nil
|
|
|
}
|
|
|
+*/
|