Skip to content

Commit 0bc66fd

Browse files
committed
Remove graceful switch from lazy and fix endpointsharding usages
1 parent 46ba28c commit 0bc66fd

File tree

7 files changed

+86
-182
lines changed

7 files changed

+86
-182
lines changed

balancer/endpointsharding/endpointsharding.go

+21-70
Original file line numberDiff line numberDiff line change
@@ -26,37 +26,17 @@
2626
package endpointsharding
2727

2828
import (
29-
"encoding/json"
3029
"errors"
31-
"fmt"
3230
rand "math/rand/v2"
3331
"sync"
3432
"sync/atomic"
3533

3634
"google.golang.org/grpc/balancer"
3735
"google.golang.org/grpc/balancer/base"
38-
"google.golang.org/grpc/balancer/pickfirst/pickfirstleaf"
3936
"google.golang.org/grpc/connectivity"
40-
"google.golang.org/grpc/grpclog"
41-
"google.golang.org/grpc/internal/balancer/gracefulswitch"
4237
"google.golang.org/grpc/resolver"
43-
"google.golang.org/grpc/serviceconfig"
4438
)
4539

46-
var (
47-
// PickFirstConfig is a pick first config without shuffling enabled.
48-
PickFirstConfig serviceconfig.LoadBalancingConfig
49-
logger = grpclog.Component("endpoint-sharding")
50-
)
51-
52-
func init() {
53-
var err error
54-
PickFirstConfig, err = ParseConfig(json.RawMessage(fmt.Sprintf("[{%q: {}}]", pickfirstleaf.Name)))
55-
if err != nil {
56-
logger.Fatal(err)
57-
}
58-
}
59-
6040
// ChildState is the balancer state of a child along with the endpoint which
6141
// identifies the child balancer.
6242
type ChildState struct {
@@ -68,36 +48,26 @@ type ChildState struct {
6848
Balancer balancer.ExitIdler
6949
}
7050

71-
// NewBalancer returns a load balancing policy that manages homogeneous child
72-
// policies each owning a single endpoint. The balancer will automatically call
73-
// ExitIdle on its children if they report IDLE connectivity state.
74-
func NewBalancer(cc balancer.ClientConn, opts balancer.BuildOptions) balancer.Balancer {
75-
return newBlanacer(cc, opts, BuildOptions{})
76-
}
77-
78-
// BuildOptions are the options to configure the behaviour of the
51+
// Options are the options to configure the behaviour of the
7952
// endpointsharding balancer.
80-
type BuildOptions struct {
53+
type Options struct {
54+
// DisableAutoReconnect allows the balancer to keep child balancer in the
55+
// IDLE state until they are explicitly triggered to exit using the
56+
// ChildState obtained from the endpointsharding picker. When set to false,
57+
// the endpointsharding balancer will automatically call ExitIdle on child
58+
// connections that report IDLE.
8159
DisableAutoReconnect bool
82-
ChildBuilder balancer.Builder
8360
}
8461

85-
// NewBalancerWithOpts returns a load balancing policy that manages
86-
// homogeneous child policies each owning a single endpoint. The balancer will
87-
// allow children to remain in IDLE state until triggered to exit idle state
88-
// using the ChildState obtained using the endpointsharding picker.
89-
func NewBalancerWithOpts(cc balancer.ClientConn, opts balancer.BuildOptions, epOpts BuildOptions) balancer.Balancer {
90-
return newBlanacer(cc, opts, epOpts)
91-
}
92-
93-
func newBlanacer(cc balancer.ClientConn, opts balancer.BuildOptions, epOpts BuildOptions) balancer.Balancer {
94-
if epOpts.ChildBuilder == nil {
95-
epOpts.ChildBuilder = &gracefulSwitchBuilder{}
96-
}
62+
// NewBalancer returns a load balancing policy that manages homogeneous child
63+
// policies each owning a single endpoint. The endpointsharding balancer
64+
// forwards the LoadBalancingConfig in ClientConn state updates to its children.
65+
func NewBalancer(cc balancer.ClientConn, opts balancer.BuildOptions, childBuilder balancer.Builder, esOpts Options) balancer.Balancer {
9766
es := &endpointSharding{
98-
cc: cc,
99-
bOpts: opts,
100-
epOpts: epOpts,
67+
cc: cc,
68+
bOpts: opts,
69+
esOpts: esOpts,
70+
childBuilder: childBuilder,
10171
}
10272
es.children.Store(resolver.NewEndpointMap())
10373
return es
@@ -107,9 +77,10 @@ func newBlanacer(cc balancer.ClientConn, opts balancer.BuildOptions, epOpts Buil
10777
// balancer with child config for every unique Endpoint received. It updates the
10878
// child states on any update from parent or child.
10979
type endpointSharding struct {
110-
cc balancer.ClientConn
111-
bOpts balancer.BuildOptions
112-
epOpts BuildOptions
80+
cc balancer.ClientConn
81+
bOpts balancer.BuildOptions
82+
esOpts Options
83+
childBuilder balancer.Builder
11384

11485
// childMu synchronizes calls to any single child. It must be held for all
11586
// calls into a child. To avoid deadlocks, do not acquire childMu while
@@ -170,7 +141,7 @@ func (es *endpointSharding) UpdateClientConnState(state balancer.ClientConnState
170141
es: es,
171142
}
172143
childBalancer.childState.Balancer = childBalancer
173-
childBalancer.child = es.epOpts.ChildBuilder.Build(childBalancer, es.bOpts)
144+
childBalancer.child = es.childBuilder.Build(childBalancer, es.bOpts)
174145
}
175146
newChildren.Set(endpoint, childBalancer)
176147
if err := childBalancer.updateClientConnStateLocked(balancer.ClientConnState{
@@ -344,7 +315,7 @@ func (bw *balancerWrapper) UpdateState(state balancer.State) {
344315
bw.es.mu.Lock()
345316
bw.childState.State = state
346317
bw.es.mu.Unlock()
347-
if state.ConnectivityState == connectivity.Idle && !bw.es.epOpts.DisableAutoReconnect {
318+
if state.ConnectivityState == connectivity.Idle && !bw.es.esOpts.DisableAutoReconnect {
348319
bw.ExitIdle()
349320
}
350321
bw.es.updateState()
@@ -380,23 +351,3 @@ func (bw *balancerWrapper) closeLocked() {
380351
bw.child.Close()
381352
bw.isClosed = true
382353
}
383-
384-
// ParseConfig parses a child config list and returns an LB config to use with
385-
// the endpointsharding balancer.
386-
//
387-
// cfg is expected to be a JSON array of LB policy names + configs as the
388-
// format of the loadBalancingConfig field in ServiceConfig.
389-
func ParseConfig(cfg json.RawMessage) (serviceconfig.LoadBalancingConfig, error) {
390-
return gracefulswitch.ParseConfig(cfg)
391-
}
392-
393-
type gracefulSwitchBuilder struct {
394-
}
395-
396-
func (b *gracefulSwitchBuilder) Build(cc balancer.ClientConn, opts balancer.BuildOptions) balancer.Balancer {
397-
return gracefulswitch.NewBalancer(cc, opts)
398-
}
399-
400-
func (b *gracefulSwitchBuilder) Name() string {
401-
return "gracefulswitch"
402-
}

balancer/endpointsharding/endpointsharding_test.go

+6-11
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"google.golang.org/grpc"
3131
"google.golang.org/grpc/balancer"
3232
"google.golang.org/grpc/balancer/endpointsharding"
33+
"google.golang.org/grpc/balancer/pickfirst/pickfirstleaf"
3334
"google.golang.org/grpc/codes"
3435
"google.golang.org/grpc/credentials/insecure"
3536
"google.golang.org/grpc/grpclog"
@@ -80,7 +81,7 @@ func (fakePetioleBuilder) Build(cc balancer.ClientConn, opts balancer.BuildOptio
8081
ClientConn: cc,
8182
bOpts: opts,
8283
}
83-
fp.Balancer = endpointsharding.NewBalancer(fp, opts)
84+
fp.Balancer = endpointsharding.NewBalancer(fp, opts, balancer.Get(pickfirstleaf.Name), endpointsharding.Options{})
8485
return fp
8586
}
8687

@@ -103,10 +104,7 @@ func (fp *fakePetiole) UpdateClientConnState(state balancer.ClientConnState) err
103104
return fmt.Errorf("UpdateClientConnState wants two endpoints, got: %v", el)
104105
}
105106

106-
return fp.Balancer.UpdateClientConnState(balancer.ClientConnState{
107-
BalancerConfig: endpointsharding.PickFirstConfig,
108-
ResolverState: state.ResolverState,
109-
})
107+
return fp.Balancer.UpdateClientConnState(state)
110108
}
111109

112110
func (fp *fakePetiole) UpdateState(state balancer.State) {
@@ -182,14 +180,11 @@ func (s) TestEndpointShardingReconnectDisabled(t *testing.T) {
182180
name := strings.ReplaceAll(strings.ToLower(t.Name()), "/", "")
183181
bf := stub.BalancerFuncs{
184182
Init: func(bd *stub.BalancerData) {
185-
epOpts := endpointsharding.BuildOptions{DisableAutoReconnect: true}
186-
bd.Data = endpointsharding.NewBalancerWithOpts(bd.ClientConn, bd.BuildOptions, epOpts)
183+
epOpts := endpointsharding.Options{DisableAutoReconnect: true}
184+
bd.Data = endpointsharding.NewBalancer(bd.ClientConn, bd.BuildOptions, balancer.Get(pickfirstleaf.Name), epOpts)
187185
},
188186
UpdateClientConnState: func(bd *stub.BalancerData, ccs balancer.ClientConnState) error {
189-
return bd.Data.(balancer.Balancer).UpdateClientConnState(balancer.ClientConnState{
190-
BalancerConfig: endpointsharding.PickFirstConfig,
191-
ResolverState: ccs.ResolverState,
192-
})
187+
return bd.Data.(balancer.Balancer).UpdateClientConnState(ccs)
193188
},
194189
Close: func(bd *stub.BalancerData) {
195190
bd.Data.(balancer.Balancer).Close()

balancer/lazy/lazy.go

+6-54
Original file line numberDiff line numberDiff line change
@@ -26,51 +26,31 @@
2626
package lazy
2727

2828
import (
29-
"encoding/json"
3029
"fmt"
3130
"sync"
3231

3332
"google.golang.org/grpc/balancer"
34-
"google.golang.org/grpc/balancer/pickfirst/pickfirstleaf"
3533
"google.golang.org/grpc/connectivity"
3634
"google.golang.org/grpc/grpclog"
37-
"google.golang.org/grpc/internal/balancer/gracefulswitch"
3835
"google.golang.org/grpc/resolver"
39-
"google.golang.org/grpc/serviceconfig"
4036

4137
internalgrpclog "google.golang.org/grpc/internal/grpclog"
4238
)
4339

44-
func init() {
45-
pfCfgJSON := fmt.Sprintf("{\"childPolicy\": [{%q: {}}]}", pickfirstleaf.Name)
46-
var err error
47-
PickfirstConfig, err = Builder{}.ParseConfig(json.RawMessage(pfCfgJSON))
48-
if err != nil {
49-
logger.Fatalf("Failed to parse pickfirst config: %v", err)
50-
}
51-
}
52-
5340
var (
54-
// PickfirstConfig is the LB policy config json for a pick_first load
55-
// balancer that is lazily initialized.
56-
PickfirstConfig serviceconfig.LoadBalancingConfig
57-
logger = grpclog.Component("lazy-lb")
41+
logger = grpclog.Component("lazy-lb")
5842
)
5943

6044
const (
61-
// Name is the name of the lazy balancer.
62-
Name = "lazy"
6345
logPrefix = "[lazy-lb %p] "
6446
)
6547

66-
// Builder builds the lazy balancer. It is not registered in the global balancer
67-
// registry by default.
68-
type Builder struct{}
69-
70-
func (Builder) Build(cc balancer.ClientConn, bOpts balancer.BuildOptions) balancer.Balancer {
48+
// NewBalancer is the constructor for the lazy balancer.
49+
func NewBalancer(cc balancer.ClientConn, bOpts balancer.BuildOptions, childBuilder balancer.Builder) balancer.Balancer {
7150
b := &lazyBalancer{
7251
cc: cc,
7352
buildOptions: bOpts,
53+
childBuilder: childBuilder,
7454
}
7555
b.logger = internalgrpclog.NewPrefixLogger(logger, fmt.Sprintf(logPrefix, b))
7656
cc.UpdateState(balancer.State{
@@ -84,16 +64,13 @@ func (Builder) Build(cc balancer.ClientConn, bOpts balancer.BuildOptions) balanc
8464
return b
8565
}
8666

87-
func (Builder) Name() string {
88-
return Name
89-
}
90-
9167
type lazyBalancer struct {
9268
// The following fields are initialized at build time and read-only after
9369
// that and therefore do not need to be guarded by a mutex.
9470
cc balancer.ClientConn
9571
buildOptions balancer.BuildOptions
9672
logger *internalgrpclog.PrefixLogger
73+
childBuilder balancer.Builder
9774

9875
// The following fields are accessed while handling calls to the idlePicker
9976
// and when handling ClientConn state updates. They are guarded by a mutex.
@@ -126,12 +103,6 @@ func (lb *lazyBalancer) ResolverError(err error) {
126103
func (lb *lazyBalancer) UpdateClientConnState(ccs balancer.ClientConnState) error {
127104
lb.mu.Lock()
128105
defer lb.mu.Unlock()
129-
childLBCfg, ok := ccs.BalancerConfig.(lbCfg)
130-
if !ok {
131-
lb.logger.Errorf("Got LB config of unexpected type: %v", ccs.BalancerConfig)
132-
return balancer.ErrBadResolverState
133-
}
134-
ccs.BalancerConfig = childLBCfg.childLBCfg
135106
if lb.delegate != nil {
136107
return lb.delegate.UpdateClientConnState(ccs)
137108
}
@@ -155,7 +126,7 @@ func (lb *lazyBalancer) ExitIdle() {
155126
}
156127
return
157128
}
158-
lb.delegate = gracefulswitch.NewBalancer(lb.cc, lb.buildOptions)
129+
lb.delegate = lb.childBuilder.Build(lb.cc, lb.buildOptions)
159130
if lb.latestClientConnState != nil {
160131
if err := lb.delegate.UpdateClientConnState(*lb.latestClientConnState); err != nil {
161132
if err == balancer.ErrBadResolverState {
@@ -172,25 +143,6 @@ func (lb *lazyBalancer) ExitIdle() {
172143
}
173144
}
174145

175-
type lbCfg struct {
176-
serviceconfig.LoadBalancingConfig
177-
childLBCfg serviceconfig.LoadBalancingConfig
178-
}
179-
180-
func (b Builder) ParseConfig(lbConfig json.RawMessage) (serviceconfig.LoadBalancingConfig, error) {
181-
jsonReprsentation := &struct {
182-
ChildPolicy json.RawMessage
183-
}{}
184-
if err := json.Unmarshal(lbConfig, jsonReprsentation); err != nil {
185-
return nil, err
186-
}
187-
childCfg, err := gracefulswitch.ParseConfig(jsonReprsentation.ChildPolicy)
188-
if err != nil {
189-
return nil, err
190-
}
191-
return lbCfg{childLBCfg: childCfg}, nil
192-
}
193-
194146
// idlePicker is used when the SubConn is IDLE and kicks the SubConn into
195147
// CONNECTING when Pick is called.
196148
type idlePicker struct {

0 commit comments

Comments
 (0)