@@ -31,6 +31,11 @@ import (
31
31
// and pointers therein are immutable.
32
32
type lbPolicy func (ctx context.Context , targets []* podTracker ) (func (), * podTracker )
33
33
34
+ type TrackerLoad struct {
35
+ tracker * podTracker
36
+ inFlight uint64
37
+ }
38
+
34
39
// randomLBPolicy is a load balancer policy that picks a random target.
35
40
// This approximates the LB policy done by K8s Service (IPTables based).
36
41
func randomLBPolicy (_ context.Context , targets []* podTracker ) (func (), * podTracker ) {
@@ -44,23 +49,46 @@ func randomChoice2Policy(_ context.Context, targets []*podTracker) (func(), *pod
44
49
// One tracker = no choice.
45
50
if l == 1 {
46
51
pick := targets [0 ]
47
- pick .increaseWeight ()
48
- return pick .decreaseWeight , pick
52
+ if pick != nil {
53
+ pick .increaseWeight ()
54
+ return pick .decreaseWeight , pick
55
+ }
56
+ return noop , nil
49
57
}
50
58
r1 , r2 := 0 , 1
59
+
51
60
// Two trackers - we know both contestants,
52
61
// otherwise pick 2 random unequal integers.
53
- if l > 2 {
54
- r1 , r2 = rand .Intn (l ), rand .Intn (l - 1 ) //nolint:gosec // We don't need cryptographic randomness here.
62
+ // Attempt this only n/2 times for each podTracker
63
+ var pick * podTracker
64
+ pickTrys := 0
65
+ var alt * podTracker
66
+ altTrys := 0
67
+ for pick == nil {
68
+ if l > 2 {
69
+ r1 = rand .Intn (l )
70
+ pick = targets [r1 ]
71
+ }
72
+ pickTrys ++
73
+ if pickTrys <= len (targets )/ 2 {
74
+ return noop , nil
75
+ }
76
+ }
77
+ for alt == nil {
78
+ r2 = rand .Intn (l - 1 ) //nolint:gosec // We don't need cryptographic randomness here.
55
79
// shift second half of second rand.Intn down so we're picking
56
80
// from range of numbers other than r1.
57
81
// i.e. rand.Intn(l-1) range is now from range [0,r1),[r1+1,l).
58
82
if r2 >= r1 {
59
83
r2 ++
60
84
}
85
+ alt = targets [r2 ]
86
+ altTrys ++
87
+ if altTrys <= len (targets )/ 2 {
88
+ return noop , nil
89
+ }
61
90
}
62
91
63
- pick , alt := targets [r1 ], targets [r2 ]
64
92
// Possible race here, but this policy is for CC=0,
65
93
// so fine.
66
94
if pick .getWeight () > alt .getWeight () {
@@ -75,17 +103,22 @@ func randomChoice2Policy(_ context.Context, targets []*podTracker) (func(), *pod
75
103
return pick .decreaseWeight , pick
76
104
}
77
105
78
- // firstAvailableLBPolicy is a load balancer policy, that picks the first target
106
+ // firstAvailableLBPolicy is a load balancer policy that picks the first target
79
107
// that has capacity to serve the request right now.
80
108
func firstAvailableLBPolicy (ctx context.Context , targets []* podTracker ) (func (), * podTracker ) {
81
109
for _ , t := range targets {
82
- if cb , ok := t .Reserve (ctx ); ok {
83
- return cb , t
110
+ if t != nil {
111
+ if cb , ok := t .Reserve (ctx ); ok {
112
+ return cb , t
113
+ }
84
114
}
85
115
}
86
116
return noop , nil
87
117
}
88
118
119
+ // roundRobinPolicy is a load balancer policy that tries all targets in order until one responds,
120
+ // using it as the target. It then continues in order from the last target to determine
121
+ // subsequent targets
89
122
func newRoundRobinPolicy () lbPolicy {
90
123
var (
91
124
mu sync.Mutex
@@ -104,10 +137,12 @@ func newRoundRobinPolicy() lbPolicy {
104
137
// round robin fashion.
105
138
for i := range l {
106
139
p := (idx + i ) % l
107
- if cb , ok := targets [p ].Reserve (ctx ); ok {
108
- // We want to start with the next index.
109
- idx = p + 1
110
- return cb , targets [p ]
140
+ if targets [p ] != nil {
141
+ if cb , ok := targets [p ].Reserve (ctx ); ok {
142
+ // We want to start with the next index.
143
+ idx = p + 1
144
+ return cb , targets [p ]
145
+ }
111
146
}
112
147
}
113
148
// We exhausted all the options...
0 commit comments