Skip to content

Commit 825fe48

Browse files
reverseproxy: Allow 0 as weights for weighted_round_robin (#6681)
* Allow 0 as weights Change positive to non-negative * reverseproxy: allow 0 as weighted round robin value * test: add more wrr select test --------- Co-authored-by: peanutduck <[email protected]>
1 parent b285763 commit 825fe48

File tree

2 files changed

+65
-6
lines changed

2 files changed

+65
-6
lines changed

modules/caddyhttp/reverseproxy/selectionpolicies.go

+13-6
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@ func (r *WeightedRoundRobinSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser)
111111
if err != nil {
112112
return d.Errf("invalid weight value '%s': %v", weight, err)
113113
}
114-
if weightInt < 1 {
115-
return d.Errf("invalid weight value '%s': weight should be non-zero and positive", weight)
114+
if weightInt < 0 {
115+
return d.Errf("invalid weight value '%s': weight should be non-negative", weight)
116116
}
117117
r.Weights = append(r.Weights, weightInt)
118118
}
@@ -136,18 +136,25 @@ func (r *WeightedRoundRobinSelection) Select(pool UpstreamPool, _ *http.Request,
136136
return pool[0]
137137
}
138138
var index, totalWeight int
139+
var weights []int
140+
141+
for _, w := range r.Weights {
142+
if w > 0 {
143+
weights = append(weights, w)
144+
}
145+
}
139146
currentWeight := int(atomic.AddUint32(&r.index, 1)) % r.totalWeight
140-
for i, weight := range r.Weights {
147+
for i, weight := range weights {
141148
totalWeight += weight
142149
if currentWeight < totalWeight {
143150
index = i
144151
break
145152
}
146153
}
147154

148-
upstreams := make([]*Upstream, 0, len(r.Weights))
149-
for _, upstream := range pool {
150-
if !upstream.Available() {
155+
upstreams := make([]*Upstream, 0, len(weights))
156+
for i, upstream := range pool {
157+
if !upstream.Available() || r.Weights[i] == 0 {
151158
continue
152159
}
153160
upstreams = append(upstreams, upstream)

modules/caddyhttp/reverseproxy/selectionpolicies_test.go

+52
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,58 @@ func TestWeightedRoundRobinPolicy(t *testing.T) {
131131
}
132132
}
133133

134+
func TestWeightedRoundRobinPolicyWithZeroWeight(t *testing.T) {
135+
pool := testPool()
136+
wrrPolicy := WeightedRoundRobinSelection{
137+
Weights: []int{0, 2, 1},
138+
totalWeight: 3,
139+
}
140+
req, _ := http.NewRequest("GET", "/", nil)
141+
142+
h := wrrPolicy.Select(pool, req, nil)
143+
if h != pool[1] {
144+
t.Error("Expected first weighted round robin host to be second host in the pool.")
145+
}
146+
147+
h = wrrPolicy.Select(pool, req, nil)
148+
if h != pool[2] {
149+
t.Error("Expected second weighted round robin host to be third host in the pool.")
150+
}
151+
152+
h = wrrPolicy.Select(pool, req, nil)
153+
if h != pool[1] {
154+
t.Error("Expected third weighted round robin host to be second host in the pool.")
155+
}
156+
157+
// mark second host as down
158+
pool[1].setHealthy(false)
159+
h = wrrPolicy.Select(pool, req, nil)
160+
if h != pool[2] {
161+
t.Error("Expect select next available host.")
162+
}
163+
164+
h = wrrPolicy.Select(pool, req, nil)
165+
if h != pool[2] {
166+
t.Error("Expect select only available host.")
167+
}
168+
// mark second host as up
169+
pool[1].setHealthy(true)
170+
171+
h = wrrPolicy.Select(pool, req, nil)
172+
if h != pool[1] {
173+
t.Error("Expect select first host on availability.")
174+
}
175+
176+
// test next select in full cycle
177+
expected := []*Upstream{pool[1], pool[2], pool[1], pool[1], pool[2], pool[1]}
178+
for i, want := range expected {
179+
got := wrrPolicy.Select(pool, req, nil)
180+
if want != got {
181+
t.Errorf("Selection %d: got host[%s], want host[%s]", i+1, got, want)
182+
}
183+
}
184+
}
185+
134186
func TestLeastConnPolicy(t *testing.T) {
135187
pool := testPool()
136188
lcPolicy := LeastConnSelection{}

0 commit comments

Comments
 (0)