use of io.grpc.ConnectivityState in project grpc-java by grpc.
the class WeightedTargetLoadBalancer method updateOverallBalancingState.
private void updateOverallBalancingState() {
List<WeightedChildPicker> childPickers = new ArrayList<>();
ConnectivityState overallState = null;
List<WeightedChildPicker> errorPickers = new ArrayList<>();
for (String name : targets.keySet()) {
ChildHelper childHelper = childHelpers.get(name);
ConnectivityState childState = childHelper.currentState;
overallState = aggregateState(overallState, childState);
int weight = targets.get(name).weight;
if (READY == childState) {
childPickers.add(new WeightedChildPicker(weight, childHelper.currentPicker));
} else if (TRANSIENT_FAILURE == childState) {
errorPickers.add(new WeightedChildPicker(weight, childHelper.currentPicker));
}
}
SubchannelPicker picker;
if (childPickers.isEmpty()) {
if (overallState == TRANSIENT_FAILURE) {
picker = new WeightedRandomPicker(errorPickers);
} else {
picker = XdsSubchannelPickers.BUFFER_PICKER;
}
} else {
picker = new WeightedRandomPicker(childPickers);
}
if (overallState != null) {
helper.updateBalancingState(overallState, picker);
}
}
use of io.grpc.ConnectivityState in project grpc-java by grpc.
the class ClusterManagerLoadBalancer method updateOverallBalancingState.
private void updateOverallBalancingState() {
ConnectivityState overallState = null;
final Map<String, SubchannelPicker> childPickers = new HashMap<>();
for (ChildLbState childLbState : childLbStates.values()) {
if (childLbState.deactivated) {
continue;
}
childPickers.put(childLbState.name, childLbState.currentPicker);
overallState = aggregateState(overallState, childLbState.currentState);
}
if (overallState != null) {
SubchannelPicker picker = new SubchannelPicker() {
@Override
public PickResult pickSubchannel(PickSubchannelArgs args) {
String clusterName = args.getCallOptions().getOption(XdsNameResolver.CLUSTER_SELECTION_KEY);
SubchannelPicker delegate = childPickers.get(clusterName);
if (delegate == null) {
return PickResult.withError(Status.UNAVAILABLE.withDescription("CDS encountered error: unable to find " + "available subchannel for cluster " + clusterName));
}
return delegate.pickSubchannel(args);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this).add("pickers", childPickers).toString();
}
};
helper.updateBalancingState(overallState, picker);
}
}
use of io.grpc.ConnectivityState in project grpc-java by grpc.
the class GrpclbState method maybeUpdatePicker.
/**
* Make and use a picker out of the current lists and the states of subchannels if they have
* changed since the last picker created.
*/
private void maybeUpdatePicker() {
List<RoundRobinEntry> pickList;
ConnectivityState state;
if (backendList.isEmpty()) {
// fail. So we should check if currently in fallback first.
if (usingFallbackBackends) {
Status error = NO_FALLBACK_BACKENDS_STATUS.withCause(fallbackReason.getCause()).augmentDescription(fallbackReason.getDescription());
pickList = Collections.<RoundRobinEntry>singletonList(new ErrorEntry(error));
state = TRANSIENT_FAILURE;
} else if (balancerWorking) {
pickList = Collections.<RoundRobinEntry>singletonList(new ErrorEntry(NO_AVAILABLE_BACKENDS_STATUS));
state = TRANSIENT_FAILURE;
} else {
// still waiting for balancer
pickList = Collections.singletonList(BUFFER_ENTRY);
state = CONNECTING;
}
maybeUpdatePicker(state, new RoundRobinPicker(dropList, pickList));
return;
}
switch(config.getMode()) {
case ROUND_ROBIN:
pickList = new ArrayList<>(backendList.size());
Status error = null;
boolean hasPending = false;
for (BackendEntry entry : backendList) {
Subchannel subchannel = entry.subchannel;
Attributes attrs = subchannel.getAttributes();
ConnectivityStateInfo stateInfo = attrs.get(STATE_INFO).get();
if (stateInfo.getState() == READY) {
pickList.add(entry);
} else if (stateInfo.getState() == TRANSIENT_FAILURE) {
error = stateInfo.getStatus();
} else {
hasPending = true;
}
}
if (pickList.isEmpty()) {
if (hasPending) {
pickList.add(BUFFER_ENTRY);
state = CONNECTING;
} else {
pickList.add(new ErrorEntry(error));
state = TRANSIENT_FAILURE;
}
} else {
state = READY;
}
break;
case PICK_FIRST:
{
checkState(backendList.size() == 1, "Excessive backend entries: %s", backendList);
BackendEntry onlyEntry = backendList.get(0);
ConnectivityStateInfo stateInfo = onlyEntry.subchannel.getAttributes().get(STATE_INFO).get();
state = stateInfo.getState();
switch(state) {
case READY:
pickList = Collections.<RoundRobinEntry>singletonList(onlyEntry);
break;
case TRANSIENT_FAILURE:
pickList = Collections.<RoundRobinEntry>singletonList(new ErrorEntry(stateInfo.getStatus()));
break;
case CONNECTING:
pickList = Collections.singletonList(BUFFER_ENTRY);
break;
default:
pickList = Collections.<RoundRobinEntry>singletonList(new IdleSubchannelEntry(onlyEntry.subchannel, syncContext));
}
break;
}
default:
throw new AssertionError("Missing case for " + config.getMode());
}
maybeUpdatePicker(state, new RoundRobinPicker(dropList, pickList));
}
use of io.grpc.ConnectivityState in project grpc-java by grpc.
the class SubchannelStateManagerImplTest method getAggregatedStatus_single.
@Test
public void getAggregatedStatus_single() {
for (ConnectivityState value : ConnectivityState.values()) {
if (value == ConnectivityState.SHUTDOWN) {
continue;
}
SubchannelStateManager stateManager = new SubchannelStateManagerImpl();
stateManager.updateState("foo", value);
assertThat(stateManager.getAggregatedState()).isEqualTo(value);
}
}
use of io.grpc.ConnectivityState in project grpc-java by grpc.
the class CachingRlsLbClientTest method get_updatesLbState.
@Test
public void get_updatesLbState() throws Exception {
setUpRlsLbClient();
InOrder inOrder = inOrder(helper);
RouteLookupRequest routeLookupRequest = RouteLookupRequest.create(ImmutableMap.of("server", "bigtable.googleapis.com", "service-key", "service1", "method-key", "create"));
rlsServerImpl.setLookupTable(ImmutableMap.of(routeLookupRequest, RouteLookupResponse.create(ImmutableList.of("primary.cloudbigtable.googleapis.com"), "header-rls-data-value")));
// valid channel
CachedRouteLookupResponse resp = getInSyncContext(routeLookupRequest);
assertThat(resp.isPending()).isTrue();
fakeTimeProvider.forwardTime(SERVER_LATENCY_MILLIS, TimeUnit.MILLISECONDS);
resp = getInSyncContext(routeLookupRequest);
assertThat(resp.hasData()).isTrue();
ArgumentCaptor<SubchannelPicker> pickerCaptor = ArgumentCaptor.forClass(SubchannelPicker.class);
ArgumentCaptor<ConnectivityState> stateCaptor = ArgumentCaptor.forClass(ConnectivityState.class);
inOrder.verify(helper, times(2)).updateBalancingState(stateCaptor.capture(), pickerCaptor.capture());
assertThat(new HashSet<>(pickerCaptor.getAllValues())).hasSize(1);
assertThat(stateCaptor.getAllValues()).containsExactly(ConnectivityState.CONNECTING, ConnectivityState.READY);
Metadata headers = new Metadata();
PickResult pickResult = pickerCaptor.getValue().pickSubchannel(new PickSubchannelArgsImpl(TestMethodDescriptors.voidMethod().toBuilder().setFullMethodName("service1/create").build(), headers, CallOptions.DEFAULT));
assertThat(pickResult.getStatus().isOk()).isTrue();
assertThat(pickResult.getSubchannel()).isNotNull();
assertThat(headers.get(RLS_DATA_KEY)).isEqualTo("header-rls-data-value");
// move backoff further back to only test error behavior
fakeBackoffProvider.nextPolicy = createBackoffPolicy(100, TimeUnit.MILLISECONDS);
// try to get invalid
RouteLookupRequest invalidRouteLookupRequest = RouteLookupRequest.create(ImmutableMap.<String, String>of());
CachedRouteLookupResponse errorResp = getInSyncContext(invalidRouteLookupRequest);
assertThat(errorResp.isPending()).isTrue();
fakeTimeProvider.forwardTime(SERVER_LATENCY_MILLIS, TimeUnit.MILLISECONDS);
errorResp = getInSyncContext(invalidRouteLookupRequest);
assertThat(errorResp.hasError()).isTrue();
// Channel is still READY because the subchannel for method /service1/create is still READY.
// Method /doesn/exists will use fallback child balancer and fail immediately.
inOrder.verify(helper).updateBalancingState(eq(ConnectivityState.READY), pickerCaptor.capture());
pickResult = pickerCaptor.getValue().pickSubchannel(new PickSubchannelArgsImpl(TestMethodDescriptors.voidMethod().toBuilder().setFullMethodName("doesn/exists").build(), headers, CallOptions.DEFAULT));
assertThat(pickResult.getStatus().getCode()).isEqualTo(Code.UNAVAILABLE);
assertThat(pickResult.getStatus().getDescription()).isEqualTo("fallback not available");
}
Aggregations