xds: use order-deterministic locality map for preserving most recent locality update to eliminate test flakiness (#5921)

* xds: use order-deterministic locality map for preserving most recent locality update to eliminate test flakiness

* make localityMap immutable
This commit is contained in:
Chengyuan Zhang 2019-06-21 15:56:37 -07:00 committed by GitHub
parent 5edd726551
commit 44bbccff79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 13 additions and 19 deletions

View File

@ -26,6 +26,7 @@ import static io.grpc.ConnectivityState.TRANSIENT_FAILURE;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.MoreObjects; import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import io.grpc.ConnectivityState; import io.grpc.ConnectivityState;
import io.grpc.ConnectivityStateInfo; import io.grpc.ConnectivityStateInfo;
import io.grpc.EquivalentAddressGroup; import io.grpc.EquivalentAddressGroup;
@ -49,9 +50,8 @@ import io.grpc.xds.XdsComms.LocalityInfo;
import io.grpc.xds.XdsSubchannelPickers.ErrorPicker; import io.grpc.xds.XdsSubchannelPickers.ErrorPicker;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -84,7 +84,7 @@ interface LocalityStore {
private final StatsStore statsStore; private final StatsStore statsStore;
private final OrcaPerRequestUtil orcaPerRequestUtil; private final OrcaPerRequestUtil orcaPerRequestUtil;
private Map<XdsLocality, LocalityLbInfo> localityMap = new HashMap<>(); private Map<XdsLocality, LocalityLbInfo> localityMap = ImmutableMap.of();
private ImmutableList<DropOverload> dropOverloads = ImmutableList.of(); private ImmutableList<DropOverload> dropOverloads = ImmutableList.of();
LocalityStoreImpl(Helper helper, LoadBalancerRegistry lbRegistry) { LocalityStoreImpl(Helper helper, LoadBalancerRegistry lbRegistry) {
@ -177,7 +177,7 @@ interface LocalityStore {
localityMap.get(locality).shutdown(); localityMap.get(locality).shutdown();
statsStore.removeLocality(locality); statsStore.removeLocality(locality);
} }
localityMap = new HashMap<>(); localityMap = ImmutableMap.of();
} }
// This is triggered by EDS response. // This is triggered by EDS response.
@ -185,20 +185,14 @@ interface LocalityStore {
public void updateLocalityStore(Map<XdsLocality, LocalityInfo> localityInfoMap) { public void updateLocalityStore(Map<XdsLocality, LocalityInfo> localityInfoMap) {
Set<XdsLocality> oldLocalities = localityMap.keySet(); Set<XdsLocality> oldLocalities = localityMap.keySet();
Set<XdsLocality> newLocalities = localityInfoMap.keySet(); Set<XdsLocality> newLocalities = localityInfoMap.keySet();
Map<XdsLocality, LocalityLbInfo> updatedLocalityMap = new LinkedHashMap<>();
final Set<XdsLocality> toRemove = new HashSet<>(); final Set<XdsLocality> toRemove = new HashSet<>();
Iterator<XdsLocality> iterator = oldLocalities.iterator(); for (XdsLocality oldLocality : oldLocalities) {
while (iterator.hasNext()) {
XdsLocality oldLocality = iterator.next();
if (!newLocalities.contains(oldLocality)) { if (!newLocalities.contains(oldLocality)) {
toRemove.add(oldLocality); toRemove.add(oldLocality);
// No graceful transition until a high-level lb graceful transition design is available. // No graceful transition until a high-level lb graceful transition design is available.
localityMap.get(oldLocality).shutdown(); localityMap.get(oldLocality).shutdown();
iterator.remove();
if (localityMap.isEmpty()) {
// down-size the map
localityMap = new HashMap<>();
}
} }
} }
@ -211,11 +205,10 @@ interface LocalityStore {
LocalityLbInfo localityLbInfo; LocalityLbInfo localityLbInfo;
ChildHelper childHelper; ChildHelper childHelper;
if (oldLocalities.contains(newLocality)) { if (oldLocalities.contains(newLocality)) {
LocalityLbInfo oldLocalityLbInfo LocalityLbInfo oldLocalityLbInfo = localityMap.get(newLocality);
= localityMap.get(newLocality);
childHelper = oldLocalityLbInfo.childHelper; childHelper = oldLocalityLbInfo.childHelper;
localityLbInfo = new LocalityLbInfo( localityLbInfo =
localityInfoMap.get(newLocality).localityWeight, new LocalityLbInfo(oldLocalityLbInfo.localityWeight,
oldLocalityLbInfo.childBalancer, oldLocalityLbInfo.childBalancer,
childHelper); childHelper);
} else { } else {
@ -226,8 +219,8 @@ interface LocalityStore {
localityInfoMap.get(newLocality).localityWeight, localityInfoMap.get(newLocality).localityWeight,
loadBalancerProvider.newLoadBalancer(childHelper), loadBalancerProvider.newLoadBalancer(childHelper),
childHelper); childHelper);
localityMap.put(newLocality, localityLbInfo);
} }
updatedLocalityMap.put(newLocality, localityLbInfo);
// TODO: put endPointWeights into attributes for WRR. // TODO: put endPointWeights into attributes for WRR.
localityLbInfo.childBalancer localityLbInfo.childBalancer
.handleResolvedAddresses( .handleResolvedAddresses(
@ -241,6 +234,7 @@ interface LocalityStore {
} }
newState = aggregateState(newState, childHelper.currentChildState); newState = aggregateState(newState, childHelper.currentChildState);
} }
localityMap = Collections.unmodifiableMap(updatedLocalityMap);
updatePicker(newState, childPickers); updatePicker(newState, childPickers);