mirror of https://github.com/grpc/grpc-go.git
balancer: fix aggregated state to not report idle with zero subconns (#4756)
This commit is contained in:
parent
d25e31e741
commit
03268c8ed2
|
@ -372,6 +372,7 @@ type ConnectivityStateEvaluator struct {
|
||||||
numReady uint64 // Number of addrConns in ready state.
|
numReady uint64 // Number of addrConns in ready state.
|
||||||
numConnecting uint64 // Number of addrConns in connecting state.
|
numConnecting uint64 // Number of addrConns in connecting state.
|
||||||
numTransientFailure uint64 // Number of addrConns in transient failure state.
|
numTransientFailure uint64 // Number of addrConns in transient failure state.
|
||||||
|
numIdle uint64 // Number of addrConns in idle state.
|
||||||
}
|
}
|
||||||
|
|
||||||
// RecordTransition records state change happening in subConn and based on that
|
// RecordTransition records state change happening in subConn and based on that
|
||||||
|
@ -380,7 +381,8 @@ type ConnectivityStateEvaluator struct {
|
||||||
// - If at least one SubConn in Ready, the aggregated state is Ready;
|
// - If at least one SubConn in Ready, the aggregated state is Ready;
|
||||||
// - Else if at least one SubConn in Connecting, the aggregated state is Connecting;
|
// - Else if at least one SubConn in Connecting, the aggregated state is Connecting;
|
||||||
// - Else if at least one SubConn is TransientFailure, the aggregated state is Transient Failure;
|
// - Else if at least one SubConn is TransientFailure, the aggregated state is Transient Failure;
|
||||||
// - Else the aggregated state is Idle
|
// - Else if at least one SubConn is Idle, the aggregated state is Idle;
|
||||||
|
// - Else there are no subconns and the aggregated state is Transient Failure
|
||||||
//
|
//
|
||||||
// Shutdown is not considered.
|
// Shutdown is not considered.
|
||||||
func (cse *ConnectivityStateEvaluator) RecordTransition(oldState, newState connectivity.State) connectivity.State {
|
func (cse *ConnectivityStateEvaluator) RecordTransition(oldState, newState connectivity.State) connectivity.State {
|
||||||
|
@ -394,6 +396,8 @@ func (cse *ConnectivityStateEvaluator) RecordTransition(oldState, newState conne
|
||||||
cse.numConnecting += updateVal
|
cse.numConnecting += updateVal
|
||||||
case connectivity.TransientFailure:
|
case connectivity.TransientFailure:
|
||||||
cse.numTransientFailure += updateVal
|
cse.numTransientFailure += updateVal
|
||||||
|
case connectivity.Idle:
|
||||||
|
cse.numIdle += updateVal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,5 +411,8 @@ func (cse *ConnectivityStateEvaluator) RecordTransition(oldState, newState conne
|
||||||
if cse.numTransientFailure > 0 {
|
if cse.numTransientFailure > 0 {
|
||||||
return connectivity.TransientFailure
|
return connectivity.TransientFailure
|
||||||
}
|
}
|
||||||
|
if cse.numIdle > 0 {
|
||||||
return connectivity.Idle
|
return connectivity.Idle
|
||||||
}
|
}
|
||||||
|
return connectivity.TransientFailure
|
||||||
|
}
|
||||||
|
|
|
@ -133,6 +133,7 @@ func (b *baseBalancer) UpdateClientConnState(s balancer.ClientConnState) error {
|
||||||
}
|
}
|
||||||
b.subConns[aNoAttrs] = subConnInfo{subConn: sc, attrs: a.Attributes}
|
b.subConns[aNoAttrs] = subConnInfo{subConn: sc, attrs: a.Attributes}
|
||||||
b.scStates[sc] = connectivity.Idle
|
b.scStates[sc] = connectivity.Idle
|
||||||
|
b.csEvltr.RecordTransition(connectivity.Shutdown, connectivity.Idle)
|
||||||
sc.Connect()
|
sc.Connect()
|
||||||
} else {
|
} else {
|
||||||
// Always update the subconn's address in case the attributes
|
// Always update the subconn's address in case the attributes
|
||||||
|
@ -213,10 +214,14 @@ func (b *baseBalancer) UpdateSubConnState(sc balancer.SubConn, state balancer.Su
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if oldS == connectivity.TransientFailure && s == connectivity.Connecting {
|
if oldS == connectivity.TransientFailure &&
|
||||||
// Once a subconn enters TRANSIENT_FAILURE, ignore subsequent
|
(s == connectivity.Connecting || s == connectivity.Idle) {
|
||||||
|
// Once a subconn enters TRANSIENT_FAILURE, ignore subsequent IDLE or
|
||||||
// CONNECTING transitions to prevent the aggregated state from being
|
// CONNECTING transitions to prevent the aggregated state from being
|
||||||
// always CONNECTING when many backends exist but are all down.
|
// always CONNECTING when many backends exist but are all down.
|
||||||
|
if s == connectivity.Idle {
|
||||||
|
sc.Connect()
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
b.scStates[sc] = s
|
b.scStates[sc] = s
|
||||||
|
@ -242,7 +247,6 @@ func (b *baseBalancer) UpdateSubConnState(sc balancer.SubConn, state balancer.Su
|
||||||
b.state == connectivity.TransientFailure {
|
b.state == connectivity.TransientFailure {
|
||||||
b.regeneratePicker()
|
b.regeneratePicker()
|
||||||
}
|
}
|
||||||
|
|
||||||
b.cc.UpdateState(balancer.State{ConnectivityState: b.state, Picker: b.picker})
|
b.cc.UpdateState(balancer.State{ConnectivityState: b.state, Picker: b.picker})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ func init() {
|
||||||
type rrPickerBuilder struct{}
|
type rrPickerBuilder struct{}
|
||||||
|
|
||||||
func (*rrPickerBuilder) Build(info base.PickerBuildInfo) balancer.Picker {
|
func (*rrPickerBuilder) Build(info base.PickerBuildInfo) balancer.Picker {
|
||||||
logger.Infof("roundrobinPicker: newPicker called with info: %v", info)
|
logger.Infof("roundrobinPicker: Build called with info: %v", info)
|
||||||
if len(info.ReadySCs) == 0 {
|
if len(info.ReadySCs) == 0 {
|
||||||
return base.NewErrPicker(balancer.ErrNoSubConnAvailable)
|
return base.NewErrPicker(balancer.ErrNoSubConnAvailable)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue