Skip to content

Commit 077dcbf

Browse files
committed
xds: Plumb locality in xds_cluster_impl and weighted_target
As part of gRFC A78: > To support the locality label in the WRR metrics, we will extend the > `weighted_target` LB policy (see A28) to define a resolver attribute > that indicates the name of its child. This attribute will be passed > down to each of its children with the appropriate value, so that any > LB policy that sits underneath the `weighted_target` policy will be > able to use it. xds_cluster_impl is involved because it uses the child names in the AddressFilter, which must match the names used by weighted_target. Instead of using Locality.toString() in multiple policies and assuming the policies agree, we now have xds_cluster_impl decide the locality's name and pass it down explicitly. This allows us to change the name format to match gRFC A78: > If locality information is available, the value of this label will be > of the form `{region="${REGION}", zone="${ZONE}", > sub_zone="${SUB_ZONE}"}`, where `${REGION}`, `${ZONE}`, and > `${SUB_ZONE}` are replaced with the actual values. If no locality > information is available, the label will be set to the empty string.
1 parent 13a9290 commit 077dcbf

9 files changed

+115
-48
lines changed

xds/src/main/java/io/grpc/xds/ClusterImplLoadBalancer.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ final class ClusterImplLoadBalancer extends LoadBalancer {
7676

7777
private static final Attributes.Key<ClusterLocalityStats> ATTR_CLUSTER_LOCALITY_STATS =
7878
Attributes.Key.create("io.grpc.xds.ClusterImplLoadBalancer.clusterLocalityStats");
79+
private static final Attributes.Key<String> ATTR_CLUSTER_LOCALITY_NAME =
80+
Attributes.Key.create("io.grpc.xds.ClusterImplLoadBalancer.clusterLocalityName");
7981

8082
private final XdsLogger logger;
8183
private final Helper helper;
@@ -209,20 +211,25 @@ public Subchannel createSubchannel(CreateSubchannelArgs args) {
209211
List<EquivalentAddressGroup> addresses = withAdditionalAttributes(args.getAddresses());
210212
Locality locality = args.getAddresses().get(0).getAttributes().get(
211213
InternalXdsAttributes.ATTR_LOCALITY); // all addresses should be in the same locality
214+
String localityName = args.getAddresses().get(0).getAttributes().get(
215+
InternalXdsAttributes.ATTR_LOCALITY_NAME);
212216
// Endpoint addresses resolved by ClusterResolverLoadBalancer should always contain
213217
// attributes with its locality, including endpoints in LOGICAL_DNS clusters.
214218
// In case of not (which really shouldn't), loads are aggregated under an empty locality.
215219
if (locality == null) {
216220
locality = Locality.create("", "", "");
221+
localityName = "";
217222
}
218223
final ClusterLocalityStats localityStats =
219224
(lrsServerInfo == null)
220225
? null
221226
: xdsClient.addClusterLocalityStats(lrsServerInfo, cluster,
222227
edsServiceName, locality);
223228

224-
Attributes attrs = args.getAttributes().toBuilder().set(
225-
ATTR_CLUSTER_LOCALITY_STATS, localityStats).build();
229+
Attributes attrs = args.getAttributes().toBuilder()
230+
.set(ATTR_CLUSTER_LOCALITY_STATS, localityStats)
231+
.set(ATTR_CLUSTER_LOCALITY_NAME, localityName)
232+
.build();
226233
args = args.toBuilder().setAddresses(addresses).setAttributes(attrs).build();
227234
final Subchannel subchannel = delegate().createSubchannel(args);
228235

@@ -344,6 +351,10 @@ public PickResult pickSubchannel(PickSubchannelArgs args) {
344351
final ClusterLocalityStats stats =
345352
result.getSubchannel().getAttributes().get(ATTR_CLUSTER_LOCALITY_STATS);
346353
if (stats != null) {
354+
String localityName =
355+
result.getSubchannel().getAttributes().get(ATTR_CLUSTER_LOCALITY_NAME);
356+
args.getPickDetailsConsumer().addOptionalLabel("grpc.lb.locality", localityName);
357+
347358
ClientStreamTracer.Factory tracerFactory = new CountingStreamTracerFactory(
348359
stats, inFlights, result.getStreamTracerFactory());
349360
ClientStreamTracer.Factory orcaTracerFactory = OrcaPerRequestUtil.getInstance()

xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancer.java

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -412,17 +412,18 @@ public void run() {
412412
if (endpoint.loadBalancingWeight() != 0) {
413413
weight *= endpoint.loadBalancingWeight();
414414
}
415+
String localityName = localityName(locality);
415416
Attributes attr =
416417
endpoint.eag().getAttributes().toBuilder()
417418
.set(InternalXdsAttributes.ATTR_LOCALITY, locality)
419+
.set(InternalXdsAttributes.ATTR_LOCALITY_NAME, localityName)
418420
.set(InternalXdsAttributes.ATTR_LOCALITY_WEIGHT,
419421
localityLbInfo.localityWeight())
420422
.set(InternalXdsAttributes.ATTR_SERVER_WEIGHT, weight)
421423
.build();
422424
EquivalentAddressGroup eag = new EquivalentAddressGroup(
423425
endpoint.eag().getAddresses(), attr);
424-
eag = AddressFilter.setPathFilter(
425-
eag, Arrays.asList(priorityName, localityName(locality)));
426+
eag = AddressFilter.setPathFilter(eag, Arrays.asList(priorityName, localityName));
426427
addresses.add(eag);
427428
}
428429
}
@@ -612,11 +613,13 @@ public void run() {
612613
for (EquivalentAddressGroup eag : resolutionResult.getAddresses()) {
613614
// No weight attribute is attached, all endpoint-level LB policy should be able
614615
// to handle such it.
615-
Attributes attr = eag.getAttributes().toBuilder().set(
616-
InternalXdsAttributes.ATTR_LOCALITY, LOGICAL_DNS_CLUSTER_LOCALITY).build();
616+
String localityName = localityName(LOGICAL_DNS_CLUSTER_LOCALITY);
617+
Attributes attr = eag.getAttributes().toBuilder()
618+
.set(InternalXdsAttributes.ATTR_LOCALITY, LOGICAL_DNS_CLUSTER_LOCALITY)
619+
.set(InternalXdsAttributes.ATTR_LOCALITY_NAME, localityName)
620+
.build();
617621
eag = new EquivalentAddressGroup(eag.getAddresses(), attr);
618-
eag = AddressFilter.setPathFilter(
619-
eag, Arrays.asList(priorityName, LOGICAL_DNS_CLUSTER_LOCALITY.toString()));
622+
eag = AddressFilter.setPathFilter(eag, Arrays.asList(priorityName, localityName));
620623
addresses.add(eag);
621624
}
622625
PriorityChildConfig priorityChildConfig = generateDnsBasedPriorityChildConfig(
@@ -844,6 +847,9 @@ private static String priorityName(String cluster, int priority) {
844847
* across all localities in all clusters.
845848
*/
846849
private static String localityName(Locality locality) {
847-
return locality.toString();
850+
return "{region=\"" + locality.region()
851+
+ "\", zone=\"" + locality.zone()
852+
+ "\", sub_zone=\"" + locality.subZone()
853+
+ "\"}";
848854
}
849855
}

xds/src/main/java/io/grpc/xds/InternalXdsAttributes.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,13 @@ public final class InternalXdsAttributes {
7777
static final Attributes.Key<Locality> ATTR_LOCALITY =
7878
Attributes.Key.create("io.grpc.xds.InternalXdsAttributes.locality");
7979

80+
/**
81+
* The name of the locality that this EquivalentAddressGroup is in.
82+
*/
83+
@EquivalentAddressGroup.Attr
84+
static final Attributes.Key<String> ATTR_LOCALITY_NAME =
85+
Attributes.Key.create("io.grpc.xds.InternalXdsAttributes.localityName");
86+
8087
/**
8188
* Endpoint weight for load balancing purposes.
8289
*/

xds/src/main/java/io/grpc/xds/WeightedTargetLoadBalancer.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import static io.grpc.ConnectivityState.TRANSIENT_FAILURE;
2424

2525
import com.google.common.collect.ImmutableMap;
26+
import io.grpc.Attributes;
2627
import io.grpc.ConnectivityState;
2728
import io.grpc.InternalLogId;
2829
import io.grpc.LoadBalancer;
@@ -42,6 +43,8 @@
4243

4344
/** Load balancer for weighted_target policy. */
4445
final class WeightedTargetLoadBalancer extends LoadBalancer {
46+
public static final Attributes.Key<String> CHILD_NAME =
47+
Attributes.Key.create("io.grpc.xds.WeightedTargetLoadBalancer.CHILD_NAME");
4548

4649
private final XdsLogger logger;
4750
private final Map<String, GracefulSwitchLoadBalancer> childBalancers = new HashMap<>();
@@ -95,6 +98,9 @@ public Status acceptResolvedAddressesInternal(ResolvedAddresses resolvedAddresse
9598
resolvedAddresses.toBuilder()
9699
.setAddresses(AddressFilter.filter(resolvedAddresses.getAddresses(), targetName))
97100
.setLoadBalancingPolicyConfig(targets.get(targetName).policySelection.getConfig())
101+
.setAttributes(resolvedAddresses.getAttributes().toBuilder()
102+
.set(CHILD_NAME, targetName)
103+
.build())
98104
.build());
99105
}
100106

xds/src/main/java/io/grpc/xds/WrrLocalityLoadBalancer.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import io.grpc.util.GracefulSwitchLoadBalancer;
3232
import io.grpc.xds.WeightedTargetLoadBalancerProvider.WeightedPolicySelection;
3333
import io.grpc.xds.WeightedTargetLoadBalancerProvider.WeightedTargetConfig;
34-
import io.grpc.xds.client.Locality;
3534
import io.grpc.xds.client.XdsLogger;
3635
import io.grpc.xds.client.XdsLogger.XdsLogLevel;
3736
import java.util.HashMap;
@@ -73,10 +72,10 @@ public Status acceptResolvedAddresses(ResolvedAddresses resolvedAddresses) {
7372
= (WrrLocalityConfig) resolvedAddresses.getLoadBalancingPolicyConfig();
7473

7574
// A map of locality weights is built up from the locality weight attributes in each address.
76-
Map<Locality, Integer> localityWeights = new HashMap<>();
75+
Map<String, Integer> localityWeights = new HashMap<>();
7776
for (EquivalentAddressGroup eag : resolvedAddresses.getAddresses()) {
7877
Attributes eagAttrs = eag.getAttributes();
79-
Locality locality = eagAttrs.get(InternalXdsAttributes.ATTR_LOCALITY);
78+
String locality = eagAttrs.get(InternalXdsAttributes.ATTR_LOCALITY_NAME);
8079
Integer localityWeight = eagAttrs.get(InternalXdsAttributes.ATTR_LOCALITY_WEIGHT);
8180

8281
if (locality == null) {
@@ -106,8 +105,8 @@ public Status acceptResolvedAddresses(ResolvedAddresses resolvedAddresses) {
106105
// Weighted target LB expects a WeightedPolicySelection for each locality as it will create a
107106
// child LB for each.
108107
Map<String, WeightedPolicySelection> weightedPolicySelections = new HashMap<>();
109-
for (Locality locality : localityWeights.keySet()) {
110-
weightedPolicySelections.put(locality.toString(),
108+
for (String locality : localityWeights.keySet()) {
109+
weightedPolicySelections.put(locality,
111110
new WeightedPolicySelection(localityWeights.get(locality),
112111
wrrLocalityConfig.childPolicy));
113112
}

xds/src/test/java/io/grpc/xds/ClusterImplLoadBalancerTest.java

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,22 @@
1919
import static com.google.common.truth.Truth.assertThat;
2020
import static org.mockito.ArgumentMatchers.anyInt;
2121
import static org.mockito.Mockito.mock;
22+
import static org.mockito.Mockito.verify;
2223
import static org.mockito.Mockito.when;
2324

2425
import com.github.xds.data.orca.v3.OrcaLoadReport;
2526
import com.google.common.collect.ImmutableMap;
2627
import com.google.common.collect.Iterables;
2728
import io.grpc.Attributes;
29+
import io.grpc.CallOptions;
2830
import io.grpc.ClientStreamTracer;
2931
import io.grpc.ConnectivityState;
3032
import io.grpc.EquivalentAddressGroup;
3133
import io.grpc.InsecureChannelCredentials;
3234
import io.grpc.LoadBalancer;
3335
import io.grpc.LoadBalancer.CreateSubchannelArgs;
3436
import io.grpc.LoadBalancer.Helper;
37+
import io.grpc.LoadBalancer.PickDetailsConsumer;
3538
import io.grpc.LoadBalancer.PickResult;
3639
import io.grpc.LoadBalancer.PickSubchannelArgs;
3740
import io.grpc.LoadBalancer.ResolvedAddresses;
@@ -45,8 +48,10 @@
4548
import io.grpc.SynchronizationContext;
4649
import io.grpc.internal.FakeClock;
4750
import io.grpc.internal.ObjectPool;
51+
import io.grpc.internal.PickSubchannelArgsImpl;
4852
import io.grpc.internal.ServiceConfigUtil.PolicySelection;
4953
import io.grpc.protobuf.ProtoUtils;
54+
import io.grpc.testing.TestMethodDescriptors;
5055
import io.grpc.xds.ClusterImplLoadBalancerProvider.ClusterImplConfig;
5156
import io.grpc.xds.Endpoints.DropOverload;
5257
import io.grpc.xds.EnvoyServerProtoData.DownstreamTlsContext;
@@ -141,6 +146,9 @@ public AtomicLong getOrCreate(String cluster, @Nullable String edsServiceName) {
141146
}
142147
};
143148
private final Helper helper = new FakeLbHelper();
149+
private PickSubchannelArgs pickSubchannelArgs = new PickSubchannelArgsImpl(
150+
TestMethodDescriptors.voidMethod(), new Metadata(), CallOptions.DEFAULT,
151+
new PickDetailsConsumer() {});
144152
@Mock
145153
private ThreadSafeRandom mockRandom;
146154
private int xdsClientRefs;
@@ -218,7 +226,7 @@ public void handleResolvedAddresses_childPolicyChanges() {
218226
public void nameResolutionError_beforeChildPolicyInstantiated_returnErrorPickerToUpstream() {
219227
loadBalancer.handleNameResolutionError(Status.UNIMPLEMENTED.withDescription("not found"));
220228
assertThat(currentState).isEqualTo(ConnectivityState.TRANSIENT_FAILURE);
221-
PickResult result = currentPicker.pickSubchannel(mock(PickSubchannelArgs.class));
229+
PickResult result = currentPicker.pickSubchannel(pickSubchannelArgs);
222230
assertThat(result.getStatus().isOk()).isFalse();
223231
assertThat(result.getStatus().getCode()).isEqualTo(Code.UNIMPLEMENTED);
224232
assertThat(result.getStatus().getDescription()).isEqualTo("not found");
@@ -243,6 +251,32 @@ public void nameResolutionError_afterChildPolicyInstantiated_propagateToDownstre
243251
.isEqualTo("cannot reach server");
244252
}
245253

254+
@Test
255+
public void pick_addsLocalityLabel() {
256+
LoadBalancerProvider weightedTargetProvider = new WeightedTargetLoadBalancerProvider();
257+
WeightedTargetConfig weightedTargetConfig =
258+
buildWeightedTargetConfig(ImmutableMap.of(locality, 10));
259+
ClusterImplConfig config = new ClusterImplConfig(CLUSTER, EDS_SERVICE_NAME, LRS_SERVER_INFO,
260+
null, Collections.<DropOverload>emptyList(),
261+
new PolicySelection(weightedTargetProvider, weightedTargetConfig), null);
262+
EquivalentAddressGroup endpoint = makeAddress("endpoint-addr", locality);
263+
deliverAddressesAndConfig(Collections.singletonList(endpoint), config);
264+
FakeLoadBalancer leafBalancer = Iterables.getOnlyElement(downstreamBalancers);
265+
Subchannel subchannel = leafBalancer.helper.createSubchannel(
266+
CreateSubchannelArgs.newBuilder().setAddresses(leafBalancer.addresses).build());
267+
leafBalancer.deliverSubchannelState(subchannel, ConnectivityState.READY);
268+
assertThat(currentState).isEqualTo(ConnectivityState.READY);
269+
270+
PickDetailsConsumer detailsConsumer = mock(PickDetailsConsumer.class);
271+
pickSubchannelArgs = new PickSubchannelArgsImpl(
272+
TestMethodDescriptors.voidMethod(), new Metadata(), CallOptions.DEFAULT, detailsConsumer);
273+
PickResult result = currentPicker.pickSubchannel(pickSubchannelArgs);
274+
assertThat(result.getStatus().isOk()).isTrue();
275+
// The value will be determined by the parent policy, so can be different than the value used in
276+
// makeAddress() for the test.
277+
verify(detailsConsumer).addOptionalLabel("grpc.lb.locality", locality.toString());
278+
}
279+
246280
@Test
247281
public void recordLoadStats() {
248282
LoadBalancerProvider weightedTargetProvider = new WeightedTargetLoadBalancerProvider();
@@ -258,7 +292,7 @@ public void recordLoadStats() {
258292
CreateSubchannelArgs.newBuilder().setAddresses(leafBalancer.addresses).build());
259293
leafBalancer.deliverSubchannelState(subchannel, ConnectivityState.READY);
260294
assertThat(currentState).isEqualTo(ConnectivityState.READY);
261-
PickResult result = currentPicker.pickSubchannel(mock(PickSubchannelArgs.class));
295+
PickResult result = currentPicker.pickSubchannel(pickSubchannelArgs);
262296
assertThat(result.getStatus().isOk()).isTrue();
263297
ClientStreamTracer streamTracer1 = result.getStreamTracerFactory().newClientStreamTracer(
264298
ClientStreamTracer.StreamInfo.newBuilder().build(), new Metadata()); // first RPC call
@@ -347,7 +381,7 @@ public void dropRpcsWithRespectToLbConfigDropCategories() {
347381
CreateSubchannelArgs.newBuilder().setAddresses(leafBalancer.addresses).build());
348382
leafBalancer.deliverSubchannelState(subchannel, ConnectivityState.READY);
349383
assertThat(currentState).isEqualTo(ConnectivityState.READY);
350-
PickResult result = currentPicker.pickSubchannel(mock(PickSubchannelArgs.class));
384+
PickResult result = currentPicker.pickSubchannel(pickSubchannelArgs);
351385
assertThat(result.getStatus().isOk()).isFalse();
352386
assertThat(result.getStatus().getCode()).isEqualTo(Code.UNAVAILABLE);
353387
assertThat(result.getStatus().getDescription()).isEqualTo("Dropped: throttle");
@@ -373,7 +407,7 @@ public void dropRpcsWithRespectToLbConfigDropCategories() {
373407
.build())
374408
.setLoadBalancingPolicyConfig(config)
375409
.build());
376-
result = currentPicker.pickSubchannel(mock(PickSubchannelArgs.class));
410+
result = currentPicker.pickSubchannel(pickSubchannelArgs);
377411
assertThat(result.getStatus().isOk()).isFalse();
378412
assertThat(result.getStatus().getCode()).isEqualTo(Code.UNAVAILABLE);
379413
assertThat(result.getStatus().getDescription()).isEqualTo("Dropped: lb");
@@ -386,7 +420,7 @@ public void dropRpcsWithRespectToLbConfigDropCategories() {
386420
.isEqualTo(1L);
387421
assertThat(clusterStats.totalDroppedRequests()).isEqualTo(1L);
388422

389-
result = currentPicker.pickSubchannel(mock(PickSubchannelArgs.class));
423+
result = currentPicker.pickSubchannel(pickSubchannelArgs);
390424
assertThat(result.getStatus().isOk()).isTrue();
391425
}
392426

@@ -423,7 +457,7 @@ private void subtest_maxConcurrentRequests_appliedByLbConfig(boolean enableCircu
423457
leafBalancer.deliverSubchannelState(subchannel, ConnectivityState.READY);
424458
assertThat(currentState).isEqualTo(ConnectivityState.READY);
425459
for (int i = 0; i < maxConcurrentRequests; i++) {
426-
PickResult result = currentPicker.pickSubchannel(mock(PickSubchannelArgs.class));
460+
PickResult result = currentPicker.pickSubchannel(pickSubchannelArgs);
427461
assertThat(result.getStatus().isOk()).isTrue();
428462
ClientStreamTracer.Factory streamTracerFactory = result.getStreamTracerFactory();
429463
streamTracerFactory.newClientStreamTracer(
@@ -434,7 +468,7 @@ private void subtest_maxConcurrentRequests_appliedByLbConfig(boolean enableCircu
434468
assertThat(clusterStats.clusterServiceName()).isEqualTo(EDS_SERVICE_NAME);
435469
assertThat(clusterStats.totalDroppedRequests()).isEqualTo(0L);
436470

437-
PickResult result = currentPicker.pickSubchannel(mock(PickSubchannelArgs.class));
471+
PickResult result = currentPicker.pickSubchannel(pickSubchannelArgs);
438472
clusterStats = Iterables.getOnlyElement(loadStatsManager.getClusterStatsReports(CLUSTER));
439473
assertThat(clusterStats.clusterServiceName()).isEqualTo(EDS_SERVICE_NAME);
440474
if (enableCircuitBreaking) {
@@ -455,15 +489,15 @@ private void subtest_maxConcurrentRequests_appliedByLbConfig(boolean enableCircu
455489
new PolicySelection(weightedTargetProvider, weightedTargetConfig), null);
456490
deliverAddressesAndConfig(Collections.singletonList(endpoint), config);
457491

458-
result = currentPicker.pickSubchannel(mock(PickSubchannelArgs.class));
492+
result = currentPicker.pickSubchannel(pickSubchannelArgs);
459493
assertThat(result.getStatus().isOk()).isTrue();
460494
result.getStreamTracerFactory().newClientStreamTracer(
461495
ClientStreamTracer.StreamInfo.newBuilder().build(), new Metadata()); // 101th request
462496
clusterStats = Iterables.getOnlyElement(loadStatsManager.getClusterStatsReports(CLUSTER));
463497
assertThat(clusterStats.clusterServiceName()).isEqualTo(EDS_SERVICE_NAME);
464498
assertThat(clusterStats.totalDroppedRequests()).isEqualTo(0L);
465499

466-
result = currentPicker.pickSubchannel(mock(PickSubchannelArgs.class)); // 102th request
500+
result = currentPicker.pickSubchannel(pickSubchannelArgs); // 102th request
467501
clusterStats = Iterables.getOnlyElement(loadStatsManager.getClusterStatsReports(CLUSTER));
468502
assertThat(clusterStats.clusterServiceName()).isEqualTo(EDS_SERVICE_NAME);
469503
if (enableCircuitBreaking) {
@@ -511,7 +545,7 @@ private void subtest_maxConcurrentRequests_appliedWithDefaultValue(
511545
leafBalancer.deliverSubchannelState(subchannel, ConnectivityState.READY);
512546
assertThat(currentState).isEqualTo(ConnectivityState.READY);
513547
for (int i = 0; i < ClusterImplLoadBalancer.DEFAULT_PER_CLUSTER_MAX_CONCURRENT_REQUESTS; i++) {
514-
PickResult result = currentPicker.pickSubchannel(mock(PickSubchannelArgs.class));
548+
PickResult result = currentPicker.pickSubchannel(pickSubchannelArgs);
515549
assertThat(result.getStatus().isOk()).isTrue();
516550
ClientStreamTracer.Factory streamTracerFactory = result.getStreamTracerFactory();
517551
streamTracerFactory.newClientStreamTracer(
@@ -522,7 +556,7 @@ private void subtest_maxConcurrentRequests_appliedWithDefaultValue(
522556
assertThat(clusterStats.clusterServiceName()).isEqualTo(EDS_SERVICE_NAME);
523557
assertThat(clusterStats.totalDroppedRequests()).isEqualTo(0L);
524558

525-
PickResult result = currentPicker.pickSubchannel(mock(PickSubchannelArgs.class));
559+
PickResult result = currentPicker.pickSubchannel(pickSubchannelArgs);
526560
clusterStats = Iterables.getOnlyElement(loadStatsManager.getClusterStatsReports(CLUSTER));
527561
assertThat(clusterStats.clusterServiceName()).isEqualTo(EDS_SERVICE_NAME);
528562
if (enableCircuitBreaking) {
@@ -697,7 +731,11 @@ public String toString() {
697731
}
698732

699733
EquivalentAddressGroup eag = new EquivalentAddressGroup(new FakeSocketAddress(name),
700-
Attributes.newBuilder().set(InternalXdsAttributes.ATTR_LOCALITY, locality).build());
734+
Attributes.newBuilder()
735+
.set(InternalXdsAttributes.ATTR_LOCALITY, locality)
736+
// Unique but arbitrary string
737+
.set(InternalXdsAttributes.ATTR_LOCALITY_NAME, locality.toString())
738+
.build());
701739
return AddressFilter.setPathFilter(eag, Collections.singletonList(locality.toString()));
702740
}
703741

0 commit comments

Comments
 (0)