Focus MultiChildLB updates around ResolvedAddresses of children

This makes ClusterManagerLB more straight-forward, focusing on just the
things that are relevant to it, and it avoids specialized map key
handling in updateChildrenWithResolvedAddresses().
This commit is contained in:
Eric Anderson 2024-07-26 09:19:14 -07:00
parent 4cb6465194
commit cfecc4754b
2 changed files with 37 additions and 84 deletions

View File

@ -16,7 +16,6 @@
package io.grpc.util; package io.grpc.util;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static io.grpc.ConnectivityState.CONNECTING; import static io.grpc.ConnectivityState.CONNECTING;
import static io.grpc.ConnectivityState.IDLE; import static io.grpc.ConnectivityState.IDLE;
@ -80,20 +79,20 @@ public abstract class MultiChildLoadBalancer extends LoadBalancer {
/** /**
* Override to utilize parsing of the policy configuration or alternative helper/lb generation. * Override to utilize parsing of the policy configuration or alternative helper/lb generation.
* Override this if keys are not Endpoints or if child policies have configuration.
*/ */
protected Map<Object, ChildLbState> createChildLbMap(ResolvedAddresses resolvedAddresses) { protected Map<Object, ResolvedAddresses> createChildAddressesMap(
Map<Object, ChildLbState> childLbMap = new HashMap<>(); ResolvedAddresses resolvedAddresses) {
List<EquivalentAddressGroup> addresses = resolvedAddresses.getAddresses(); Map<Object, ResolvedAddresses> childAddresses = new HashMap<>();
for (EquivalentAddressGroup eag : addresses) { for (EquivalentAddressGroup eag : resolvedAddresses.getAddresses()) {
Endpoint endpoint = new Endpoint(eag); // keys need to be just addresses ResolvedAddresses addresses = resolvedAddresses.toBuilder()
ChildLbState existingChildLbState = childLbStates.get(endpoint); .setAddresses(Collections.singletonList(eag))
if (existingChildLbState != null) { .setAttributes(Attributes.newBuilder().set(IS_PETIOLE_POLICY, true).build())
childLbMap.put(endpoint, existingChildLbState); .setLoadBalancingPolicyConfig(null)
} else { .build();
childLbMap.put(endpoint, createChildLbState(endpoint)); childAddresses.put(new Endpoint(eag), addresses);
} }
} return childAddresses;
return childLbMap;
} }
/** /**
@ -128,39 +127,6 @@ public abstract class MultiChildLoadBalancer extends LoadBalancer {
} }
} }
/**
* Override this if your keys are not of type Endpoint.
* @param key Key to identify the ChildLbState
* @param resolvedAddresses list of addresses which include attributes
* @return a fully loaded ResolvedAddresses object for the specified key
*/
protected ResolvedAddresses getChildAddresses(Object key, ResolvedAddresses resolvedAddresses) {
Endpoint endpointKey;
if (key instanceof EquivalentAddressGroup) {
endpointKey = new Endpoint((EquivalentAddressGroup) key);
} else {
checkArgument(key instanceof Endpoint, "key is wrong type");
endpointKey = (Endpoint) key;
}
// Retrieve the non-stripped version
EquivalentAddressGroup eagToUse = null;
for (EquivalentAddressGroup currEag : resolvedAddresses.getAddresses()) {
if (endpointKey.equals(new Endpoint(currEag))) {
eagToUse = currEag;
break;
}
}
checkNotNull(eagToUse, key + " no longer present in load balancer children");
return resolvedAddresses.toBuilder()
.setAddresses(Collections.singletonList(eagToUse))
.setAttributes(Attributes.newBuilder().set(IS_PETIOLE_POLICY, true).build())
.setLoadBalancingPolicyConfig(null)
.build();
}
/** /**
* Handle the name resolution error. * Handle the name resolution error.
* *
@ -192,41 +158,31 @@ public abstract class MultiChildLoadBalancer extends LoadBalancer {
ResolvedAddresses resolvedAddresses) { ResolvedAddresses resolvedAddresses) {
logger.log(Level.FINE, "Received resolution result: {0}", resolvedAddresses); logger.log(Level.FINE, "Received resolution result: {0}", resolvedAddresses);
// Subclass handles any special manipulation to create appropriate types of keyed ChildLbStates Map<Object, ResolvedAddresses> newChildAddresses = createChildAddressesMap(resolvedAddresses);
Map<Object, ChildLbState> newChildren = createChildLbMap(resolvedAddresses);
// Handle error case // Handle error case
if (newChildren.isEmpty()) { if (newChildAddresses.isEmpty()) {
Status unavailableStatus = Status.UNAVAILABLE.withDescription( Status unavailableStatus = Status.UNAVAILABLE.withDescription(
"NameResolver returned no usable address. " + resolvedAddresses); "NameResolver returned no usable address. " + resolvedAddresses);
handleNameResolutionError(unavailableStatus); handleNameResolutionError(unavailableStatus);
return new AcceptResolvedAddrRetVal(unavailableStatus, null); return new AcceptResolvedAddrRetVal(unavailableStatus, null);
} }
addMissingChildren(newChildren); updateChildrenWithResolvedAddresses(newChildAddresses);
updateChildrenWithResolvedAddresses(resolvedAddresses, newChildren); return new AcceptResolvedAddrRetVal(Status.OK, getRemovedChildren(newChildAddresses.keySet()));
return new AcceptResolvedAddrRetVal(Status.OK, getRemovedChildren(newChildren.keySet()));
} }
private void addMissingChildren(Map<Object, ChildLbState> newChildren) { private void updateChildrenWithResolvedAddresses(
// Do adds and identify reused children Map<Object, ResolvedAddresses> newChildAddresses) {
for (Map.Entry<Object, ChildLbState> entry : newChildren.entrySet()) { for (Map.Entry<Object, ResolvedAddresses> entry : newChildAddresses.entrySet()) {
final Object key = entry.getKey();
if (!childLbStates.containsKey(key)) {
childLbStates.put(key, entry.getValue());
}
}
}
private void updateChildrenWithResolvedAddresses(ResolvedAddresses resolvedAddresses,
Map<Object, ChildLbState> newChildren) {
for (Map.Entry<Object, ChildLbState> entry : newChildren.entrySet()) {
ChildLbState childLbState = childLbStates.get(entry.getKey()); ChildLbState childLbState = childLbStates.get(entry.getKey());
ResolvedAddresses childAddresses = getChildAddresses(entry.getKey(), resolvedAddresses); if (childLbState == null) {
childLbState.setResolvedAddresses(childAddresses); // update child childLbState = createChildLbState(entry.getKey());
childLbState.lb.handleResolvedAddresses(childAddresses); // update child LB childLbStates.put(entry.getKey(), childLbState);
}
childLbState.setResolvedAddresses(entry.getValue()); // update child
childLbState.lb.handleResolvedAddresses(entry.getValue()); // update child LB
} }
} }

View File

@ -70,31 +70,28 @@ class ClusterManagerLoadBalancer extends MultiChildLoadBalancer {
} }
@Override @Override
protected ResolvedAddresses getChildAddresses(Object key, ResolvedAddresses resolvedAddresses) { protected ChildLbState createChildLbState(Object key) {
ClusterManagerConfig config = (ClusterManagerConfig) return new ClusterManagerLbState(key, GracefulSwitchLoadBalancerFactory.INSTANCE);
resolvedAddresses.getLoadBalancingPolicyConfig();
Object childConfig = config.childPolicies.get(key);
return resolvedAddresses.toBuilder().setLoadBalancingPolicyConfig(childConfig).build();
} }
@Override @Override
protected Map<Object, ChildLbState> createChildLbMap(ResolvedAddresses resolvedAddresses) { protected Map<Object, ResolvedAddresses> createChildAddressesMap(
ResolvedAddresses resolvedAddresses) {
ClusterManagerConfig config = (ClusterManagerConfig) ClusterManagerConfig config = (ClusterManagerConfig)
resolvedAddresses.getLoadBalancingPolicyConfig(); resolvedAddresses.getLoadBalancingPolicyConfig();
Map<Object, ChildLbState> newChildPolicies = new HashMap<>(); Map<Object, ResolvedAddresses> childAddresses = new HashMap<>();
if (config != null) { if (config != null) {
for (String key : config.childPolicies.keySet()) { for (Map.Entry<String, Object> childPolicy : config.childPolicies.entrySet()) {
ChildLbState child = getChildLbState(key); ResolvedAddresses addresses = resolvedAddresses.toBuilder()
if (child == null) { .setLoadBalancingPolicyConfig(childPolicy.getValue())
child = new ClusterManagerLbState(key, GracefulSwitchLoadBalancerFactory.INSTANCE); .build();
} childAddresses.put(childPolicy.getKey(), addresses);
newChildPolicies.put(key, child);
} }
} }
logger.log( logger.log(
XdsLogLevel.INFO, XdsLogLevel.INFO,
"Received cluster_manager lb config: child names={0}", newChildPolicies.keySet()); "Received cluster_manager lb config: child names={0}", childAddresses.keySet());
return newChildPolicies; return childAddresses;
} }
/** /**