Skip to content

Commit 3907d39

Browse files
committed
rls: delegate pick to child policy as long as it is not in TransientFailure
1 parent 7da8a05 commit 3907d39

File tree

2 files changed

+18
-29
lines changed

2 files changed

+18
-29
lines changed

balancer/rls/picker.go

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -162,16 +162,17 @@ func (p *rlsPicker) Pick(info balancer.PickInfo) (balancer.PickResult, error) {
162162

163163
// delegateToChildPolicies is a helper function which iterates through the list
164164
// of child policy wrappers in a cache entry and attempts to find a child policy
165-
// to which this RPC can be routed to. If there is no child policy in READY
166-
// state, we delegate to the first child policy arbitrarily.
165+
// to which this RPC can be routed to. If all child policies are in
166+
// TRANSIENT_FAILURE, we delegate to the first child policy arbitrarily.
167167
//
168168
// Caller must hold at least a read-lock on p.lb.cacheMu.
169169
func (p *rlsPicker) delegateToChildPolicies(dcEntry *cacheEntry, info balancer.PickInfo) (balancer.PickResult, error) {
170170
for _, cpw := range dcEntry.childPolicyWrappers {
171-
ok, res, err := p.pickIfFeasible(cpw, info)
172-
if ok {
173-
return res, err
171+
state := (*balancer.State)(atomic.LoadPointer(&cpw.state))
172+
if state.ConnectivityState == connectivity.TransientFailure {
173+
continue
174174
}
175+
return state.Picker.Pick(info)
175176
}
176177
if len(dcEntry.childPolicyWrappers) != 0 {
177178
state := (*balancer.State)(atomic.LoadPointer(&dcEntry.childPolicyWrappers[0].state))
@@ -249,8 +250,8 @@ func (p *rlsPicker) sendRequestAndReturnPick(cacheKey cacheKey, bs *backoffState
249250
// target if one is configured, or fails the pick with the given error.
250251
func (p *rlsPicker) useDefaultPickIfPossible(info balancer.PickInfo, errOnNoDefault error) (balancer.PickResult, error) {
251252
if p.defaultPolicy != nil {
252-
_, res, err := p.pickIfFeasible(p.defaultPolicy, info)
253-
return res, err
253+
state := (*balancer.State)(atomic.LoadPointer(&p.defaultPolicy.state))
254+
return state.Picker.Pick(info)
254255
}
255256
return balancer.PickResult{}, errOnNoDefault
256257
}
@@ -275,27 +276,6 @@ func (p *rlsPicker) sendRouteLookupRequest(cacheKey cacheKey, bs *backoffState,
275276
return throttled
276277
}
277278

278-
// pickIfFeasible determines if a pick can be delegated to child policy based on
279-
// its connectivity state.
280-
// - If state is CONNECTING, the pick is to be queued
281-
// - If state is IDLE, the child policy is instructed to exit idle, and the pick
282-
// is to be queued
283-
// - If state is READY, pick it delegated to the child policy's picker
284-
func (p *rlsPicker) pickIfFeasible(cpw *childPolicyWrapper, info balancer.PickInfo) (bool, balancer.PickResult, error) {
285-
state := (*balancer.State)(atomic.LoadPointer(&cpw.state))
286-
switch state.ConnectivityState {
287-
case connectivity.Connecting:
288-
return true, balancer.PickResult{}, balancer.ErrNoSubConnAvailable
289-
case connectivity.Idle:
290-
p.bg.ExitIdleOne(cpw.target)
291-
return true, balancer.PickResult{}, balancer.ErrNoSubConnAvailable
292-
case connectivity.Ready:
293-
r, e := state.Picker.Pick(info)
294-
return true, r, e
295-
}
296-
return false, balancer.PickResult{}, balancer.ErrNoSubConnAvailable
297-
}
298-
299279
// handleRouteLookupResponse is the callback invoked by the control channel upon
300280
// receipt of an RLS response. Modifies the data cache and pending requests map
301281
// and sends a new picker.

internal/testutils/xds/e2e/clientresources.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525

2626
"github.com/envoyproxy/go-control-plane/pkg/wellknown"
2727
"github.com/golang/protobuf/proto"
28+
"google.golang.org/grpc/internal/grpcrand"
2829
"google.golang.org/grpc/internal/testutils"
2930

3031
v3clusterpb "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3"
@@ -333,6 +334,14 @@ func DefaultCluster(clusterName, edsServiceName string, secLevel SecurityLevel)
333334
}
334335
}
335336

337+
// A simple hack to ensure that our e2e tests run with both ring_hash and
338+
// weighted_target LB policies. This will not ensure an equal split between
339+
// the two LB polciies, but will most definitely end up using both of them.
340+
lbPolicy := v3clusterpb.Cluster_ROUND_ROBIN
341+
if grpcrand.Intn(100) < 50 {
342+
lbPolicy = v3clusterpb.Cluster_RING_HASH
343+
}
344+
336345
cluster := &v3clusterpb.Cluster{
337346
Name: clusterName,
338347
ClusterDiscoveryType: &v3clusterpb.Cluster_Type{Type: v3clusterpb.Cluster_EDS},
@@ -344,7 +353,7 @@ func DefaultCluster(clusterName, edsServiceName string, secLevel SecurityLevel)
344353
},
345354
ServiceName: edsServiceName,
346355
},
347-
LbPolicy: v3clusterpb.Cluster_ROUND_ROBIN,
356+
LbPolicy: lbPolicy,
348357
}
349358
if tlsContext != nil {
350359
cluster.TransportSocket = &v3corepb.TransportSocket{

0 commit comments

Comments
 (0)