mirror of https://github.com/grpc/grpc-java.git
core: round robin should ignore name resolution error for channel state change when there are READY subchannels (#7595)
Round robin is keeping use of READY subchannels even if there is name resolution error. However, it moves Channel state to TRANSIENT_ERROR. In hierarchical load balancers, the upstream LB policy may need to aggregate pickers from multiple downstream round_robin LB policy while filtering out non-ready subchannels. It cannot infer if the subchannel can be used just from the SubchannelPicker interface. It relies on the state that the round_robin intends to set channel to. So the change is to match the readiness of the picker/subchannel with the state that round_robin tries to update. It will completely ignore name resolution error if there are READY subchannels.
This commit is contained in:
parent
8020a735f9
commit
10dc41af74
|
|
@ -130,9 +130,9 @@ final class RoundRobinLoadBalancer extends LoadBalancer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleNameResolutionError(Status error) {
|
public void handleNameResolutionError(Status error) {
|
||||||
// ready pickers aren't affected by status changes
|
if (currentState != READY) {
|
||||||
updateBalancingState(TRANSIENT_FAILURE,
|
updateBalancingState(TRANSIENT_FAILURE, new EmptyPicker(error));
|
||||||
currentPicker instanceof ReadyPicker ? currentPicker : new EmptyPicker(error));
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processSubchannelState(Subchannel subchannel, ConnectivityStateInfo stateInfo) {
|
private void processSubchannelState(Subchannel subchannel, ConnectivityStateInfo stateInfo) {
|
||||||
|
|
|
||||||
|
|
@ -381,13 +381,12 @@ public class RoundRobinLoadBalancerTest {
|
||||||
loadBalancer.handleNameResolutionError(Status.NOT_FOUND.withDescription("nameResolutionError"));
|
loadBalancer.handleNameResolutionError(Status.NOT_FOUND.withDescription("nameResolutionError"));
|
||||||
|
|
||||||
verify(mockHelper, times(3)).createSubchannel(any(CreateSubchannelArgs.class));
|
verify(mockHelper, times(3)).createSubchannel(any(CreateSubchannelArgs.class));
|
||||||
verify(mockHelper, times(3))
|
verify(mockHelper, times(2))
|
||||||
.updateBalancingState(stateCaptor.capture(), pickerCaptor.capture());
|
.updateBalancingState(stateCaptor.capture(), pickerCaptor.capture());
|
||||||
|
|
||||||
Iterator<ConnectivityState> stateIterator = stateCaptor.getAllValues().iterator();
|
Iterator<ConnectivityState> stateIterator = stateCaptor.getAllValues().iterator();
|
||||||
assertEquals(CONNECTING, stateIterator.next());
|
assertEquals(CONNECTING, stateIterator.next());
|
||||||
assertEquals(READY, stateIterator.next());
|
assertEquals(READY, stateIterator.next());
|
||||||
assertEquals(TRANSIENT_FAILURE, stateIterator.next());
|
|
||||||
|
|
||||||
LoadBalancer.PickResult pickResult = pickerCaptor.getValue().pickSubchannel(mockArgs);
|
LoadBalancer.PickResult pickResult = pickerCaptor.getValue().pickSubchannel(mockArgs);
|
||||||
assertEquals(readySubchannel, pickResult.getSubchannel());
|
assertEquals(readySubchannel, pickResult.getSubchannel());
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue