mirror of https://github.com/grpc/grpc-java.git
xds: provide more debug info for priority lb error-picker
When all priorities fail, update the overall picker with the picker from the last priority. This still does not provide the full detail why all priorities fail but is better than nothing being provided currently.
This commit is contained in:
parent
814e36b541
commit
90e3dcf1ae
|
@ -153,7 +153,9 @@ final class PriorityLoadBalancer extends LoadBalancer {
|
|||
}
|
||||
// TODO(zdapeng): Include error details of each priority.
|
||||
logger.log(XdsLogLevel.DEBUG, "All priority failed");
|
||||
updateOverallState(TRANSIENT_FAILURE, new ErrorPicker(Status.UNAVAILABLE));
|
||||
String lastPriority = priorityNames.get(priorityNames.size() - 1);
|
||||
SubchannelPicker errorPicker = children.get(lastPriority).picker;
|
||||
updateOverallState(TRANSIENT_FAILURE, errorPicker);
|
||||
}
|
||||
|
||||
private void updateOverallState(ConnectivityState state, SubchannelPicker picker) {
|
||||
|
@ -190,6 +192,8 @@ final class PriorityLoadBalancer extends LoadBalancer {
|
|||
// The child is deactivated.
|
||||
return;
|
||||
}
|
||||
picker = new ErrorPicker(
|
||||
Status.UNAVAILABLE.withDescription("Connection timeout for priority " + priority));
|
||||
logger.log(XdsLogLevel.DEBUG, "Priority {0} failed over to next", priority);
|
||||
tryNextPriority(true);
|
||||
}
|
||||
|
|
|
@ -281,7 +281,7 @@ public class PriorityLoadBalancerTest {
|
|||
return PickResult.withSubchannel(subchannel0);
|
||||
}
|
||||
});
|
||||
assertLatestSubchannelPicker(subchannel0);
|
||||
assertCurrentPickerPicksSubchannel(subchannel0);
|
||||
|
||||
// p0 fails over to p1 immediately.
|
||||
helper0.updateBalancingState(TRANSIENT_FAILURE, new ErrorPicker(Status.ABORTED));
|
||||
|
@ -308,7 +308,7 @@ public class PriorityLoadBalancerTest {
|
|||
return PickResult.withSubchannel(subchannel1);
|
||||
}
|
||||
});
|
||||
assertLatestSubchannelPicker(subchannel1);
|
||||
assertCurrentPickerPicksSubchannel(subchannel1);
|
||||
|
||||
// p0 gets back to READY
|
||||
final Subchannel subchannel2 = mock(Subchannel.class);
|
||||
|
@ -320,11 +320,11 @@ public class PriorityLoadBalancerTest {
|
|||
return PickResult.withSubchannel(subchannel2);
|
||||
}
|
||||
});
|
||||
assertLatestSubchannelPicker(subchannel2);
|
||||
assertCurrentPickerPicksSubchannel(subchannel2);
|
||||
|
||||
// p2 fails but does not affect overall picker
|
||||
helper2.updateBalancingState(TRANSIENT_FAILURE, new ErrorPicker(Status.UNAVAILABLE));
|
||||
assertLatestSubchannelPicker(subchannel2);
|
||||
assertCurrentPickerPicksSubchannel(subchannel2);
|
||||
|
||||
// p0 fails over to p3 immediately since p1 already timeout and p2 already in TRANSIENT_FAILURE.
|
||||
helper0.updateBalancingState(TRANSIENT_FAILURE, new ErrorPicker(Status.UNAVAILABLE));
|
||||
|
@ -334,9 +334,14 @@ public class PriorityLoadBalancerTest {
|
|||
LoadBalancer balancer3 = Iterables.getLast(fooBalancers);
|
||||
Helper helper3 = Iterables.getLast(fooHelpers);
|
||||
|
||||
// p3 fails then the channel should go to TRANSIENT_FAILURE
|
||||
helper3.updateBalancingState(TRANSIENT_FAILURE, new ErrorPicker(Status.UNAVAILABLE));
|
||||
assertLatestConnectivityState(TRANSIENT_FAILURE);
|
||||
// p3 timeout then the channel should go to TRANSIENT_FAILURE
|
||||
fakeClock.forwardTime(10, TimeUnit.SECONDS);
|
||||
assertCurrentPickerReturnsError(Status.Code.UNAVAILABLE, "timeout");
|
||||
|
||||
// p3 fails then the picker should have error status updated
|
||||
helper3.updateBalancingState(
|
||||
TRANSIENT_FAILURE, new ErrorPicker(Status.DATA_LOSS.withDescription("foo")));
|
||||
assertCurrentPickerReturnsError(Status.Code.DATA_LOSS, "foo");
|
||||
|
||||
// p2 gets back to READY
|
||||
final Subchannel subchannel3 = mock(Subchannel.class);
|
||||
|
@ -348,7 +353,7 @@ public class PriorityLoadBalancerTest {
|
|||
return PickResult.withSubchannel(subchannel3);
|
||||
}
|
||||
});
|
||||
assertLatestSubchannelPicker(subchannel3);
|
||||
assertCurrentPickerPicksSubchannel(subchannel3);
|
||||
|
||||
// p0 gets back to READY
|
||||
final Subchannel subchannel4 = mock(Subchannel.class);
|
||||
|
@ -360,11 +365,11 @@ public class PriorityLoadBalancerTest {
|
|||
return PickResult.withSubchannel(subchannel4);
|
||||
}
|
||||
});
|
||||
assertLatestSubchannelPicker(subchannel4);
|
||||
assertCurrentPickerPicksSubchannel(subchannel4);
|
||||
|
||||
// p0 fails over to p2 and picker is updated to p2's existing picker.
|
||||
helper0.updateBalancingState(TRANSIENT_FAILURE, new ErrorPicker(Status.UNAVAILABLE));
|
||||
assertLatestSubchannelPicker(subchannel3);
|
||||
assertCurrentPickerPicksSubchannel(subchannel3);
|
||||
|
||||
// Deactivate child balancer get deleted.
|
||||
fakeClock.forwardTime(15, TimeUnit.MINUTES);
|
||||
|
@ -380,10 +385,20 @@ public class PriorityLoadBalancerTest {
|
|||
assertThat(connectivityStateCaptor.getValue()).isEqualTo(expectedState);
|
||||
}
|
||||
|
||||
private void assertLatestSubchannelPicker(Subchannel expectedSubchannelToPick) {
|
||||
private void assertCurrentPickerReturnsError(
|
||||
Status.Code expectedCode, String expectedDescription) {
|
||||
assertLatestConnectivityState(TRANSIENT_FAILURE);
|
||||
Status error =
|
||||
pickerCaptor.getValue().pickSubchannel(mock(PickSubchannelArgs.class)).getStatus();
|
||||
assertThat(error.getCode()).isEqualTo(expectedCode);
|
||||
if (expectedDescription != null) {
|
||||
assertThat(error.getDescription()).contains(expectedDescription);
|
||||
}
|
||||
}
|
||||
|
||||
private void assertCurrentPickerPicksSubchannel(Subchannel expectedSubchannelToPick) {
|
||||
assertLatestConnectivityState(READY);
|
||||
assertThat(
|
||||
pickerCaptor.getValue().pickSubchannel(mock(PickSubchannelArgs.class)).getSubchannel())
|
||||
.isEqualTo(expectedSubchannelToPick);
|
||||
PickResult pickResult = pickerCaptor.getValue().pickSubchannel(mock(PickSubchannelArgs.class));
|
||||
assertThat(pickResult.getSubchannel()).isEqualTo(expectedSubchannelToPick);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue