diff --git a/fe/lbv2/lbv2.go b/fe/lbv2/lbv2.go index dac92092d3d7097f624fc64cdf8464ecc1c2bc62..031edb032fa028749926a5dfa8e9735b00bbe164 100644 --- a/fe/lbv2/lbv2.go +++ b/fe/lbv2/lbv2.go @@ -293,7 +293,13 @@ type capacityAvailableScorer struct { } func (s *capacityAvailableScorer) Score(ctx RequestContext, n Node) float64 { - return 1.0 / s.pred.Utilization(n) + // Cap utilization low limit at 5%. Anything below that is + // considered equally available. + u := s.pred.Utilization(n) + if u < 0.05 { + u = 0.05 + } + return 1.0 / u } func NewCapacityAvailableScorer(pred Predictor) NodeFilter { diff --git a/fe/loadbalancing_test.go b/fe/loadbalancing_test.go index 4ca4ec0923e42319057a615088c9010efa6a84aa..2b3c7a49a443db9a8dc100a970b88a068f60b8f2 100644 --- a/fe/loadbalancing_test.go +++ b/fe/loadbalancing_test.go @@ -115,6 +115,24 @@ func TestLoadBalancer_Policies(t *testing.T) { runLBTest(t, nodes, nil, "bandwidth_score,best", 1000, map[string]int{"node2": 1000}) } +func TestLoadBalancer_ZeroUtilization(t *testing.T) { + nodes := []*autoradio.NodeStatus{ + &autoradio.NodeStatus{ + Name: "node1", + IcecastUp: true, + BandwidthUsage: 0, + }, + &autoradio.NodeStatus{ + Name: "node2", + IcecastUp: true, + BandwidthUsage: 0, + }, + } + + // Weighted should return both nodes equally. + runLBTest(t, nodes, nil, "bandwidth_score,weighted", 1000, map[string]int{"node1": 500, "node2": 500}) +} + func TestLoadBalancer_PoliciesIgnoreDisabledNodes(t *testing.T) { nodes := []*autoradio.NodeStatus{ &autoradio.NodeStatus{