diff --git a/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancer.java b/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancer.java index 1eaef890b5..9cfbe3a753 100644 --- a/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancer.java +++ b/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancer.java @@ -387,13 +387,17 @@ final class ClusterResolverLoadBalancer extends LoadBalancer { for (LbEndpoint endpoint : localityLbInfo.endpoints()) { if (endpoint.isHealthy()) { discard = false; - long weight = - (long) localityLbInfo.localityWeight() * endpoint.loadBalancingWeight(); - Attributes attr = endpoint.eag().getAttributes().toBuilder() - .set(InternalXdsAttributes.ATTR_LOCALITY, locality) - .set(InternalXdsAttributes.ATTR_SERVER_WEIGHT, weight).build(); - EquivalentAddressGroup eag = - new EquivalentAddressGroup(endpoint.eag().getAddresses(), attr); + long weight = localityLbInfo.localityWeight(); + if (endpoint.loadBalancingWeight() != 0) { + weight *= endpoint.loadBalancingWeight(); + } + Attributes attr = + endpoint.eag().getAttributes().toBuilder() + .set(InternalXdsAttributes.ATTR_LOCALITY, locality) + .set(InternalXdsAttributes.ATTR_SERVER_WEIGHT, weight) + .build(); + EquivalentAddressGroup eag = new EquivalentAddressGroup( + endpoint.eag().getAddresses(), attr); eag = AddressFilter.setPathFilter( eag, Arrays.asList(priorityName, localityName(locality))); addresses.add(eag); diff --git a/xds/src/main/java/io/grpc/xds/Endpoints.java b/xds/src/main/java/io/grpc/xds/Endpoints.java index 5f871c9d26..8b1715731d 100644 --- a/xds/src/main/java/io/grpc/xds/Endpoints.java +++ b/xds/src/main/java/io/grpc/xds/Endpoints.java @@ -16,6 +16,8 @@ package io.grpc.xds; +import static com.google.common.base.Preconditions.checkArgument; + import com.google.auto.value.AutoValue; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; @@ -33,7 +35,7 @@ final class Endpoints { // Endpoints to be load balanced. abstract ImmutableList endpoints(); - // Locality's weight for inter-locality load balancing. + // Locality's weight for inter-locality load balancing. Guaranteed to be greater than 0. abstract int localityWeight(); // Locality's priority level. @@ -41,6 +43,7 @@ final class Endpoints { static LocalityLbEndpoints create(List endpoints, int localityWeight, int priority) { + checkArgument(localityWeight > 0, "localityWeight must be greater than 0"); return new AutoValue_Endpoints_LocalityLbEndpoints( ImmutableList.copyOf(endpoints), localityWeight, priority); } @@ -52,7 +55,7 @@ final class Endpoints { // The endpoint address to be connected to. abstract EquivalentAddressGroup eag(); - // Endpoint's wight for load balancing. + // Endpoint's weight for load balancing. If unspecified, value of 0 is returned. abstract int loadBalancingWeight(); // Whether the endpoint is healthy. diff --git a/xds/src/test/java/io/grpc/xds/ClusterResolverLoadBalancerTest.java b/xds/src/test/java/io/grpc/xds/ClusterResolverLoadBalancerTest.java index 1e334c749b..b987ca95c3 100644 --- a/xds/src/test/java/io/grpc/xds/ClusterResolverLoadBalancerTest.java +++ b/xds/src/test/java/io/grpc/xds/ClusterResolverLoadBalancerTest.java @@ -217,29 +217,37 @@ public class ClusterResolverLoadBalancerTest { // One priority with two localities of different weights. EquivalentAddressGroup endpoint1 = makeAddress("endpoint-addr-1"); EquivalentAddressGroup endpoint2 = makeAddress("endpoint-addr-2"); + EquivalentAddressGroup endpoint3 = makeAddress("endpoint-addr-3"); LocalityLbEndpoints localityLbEndpoints1 = LocalityLbEndpoints.create( - Collections.singletonList( - LbEndpoint.create(endpoint1, 100 /* loadBalancingWeight */, true)), + Arrays.asList( + LbEndpoint.create(endpoint1, 0 /* loadBalancingWeight */, true), + LbEndpoint.create(endpoint2, 0 /* loadBalancingWeight */, true)), 10 /* localityWeight */, 1 /* priority */); LocalityLbEndpoints localityLbEndpoints2 = LocalityLbEndpoints.create( Collections.singletonList( - LbEndpoint.create(endpoint2, 60 /* loadBalancingWeight */, true)), + LbEndpoint.create(endpoint3, 60 /* loadBalancingWeight */, true)), 50 /* localityWeight */, 1 /* priority */); xdsClient.deliverClusterLoadAssignment( EDS_SERVICE_NAME1, ImmutableMap.of(locality1, localityLbEndpoints1, locality2, localityLbEndpoints2)); assertThat(childBalancers).hasSize(1); FakeLoadBalancer childBalancer = Iterables.getOnlyElement(childBalancers); - assertThat(childBalancer.addresses).hasSize(2); + assertThat(childBalancer.addresses).hasSize(3); EquivalentAddressGroup addr1 = childBalancer.addresses.get(0); EquivalentAddressGroup addr2 = childBalancer.addresses.get(1); + EquivalentAddressGroup addr3 = childBalancer.addresses.get(2); + // Endpoints in locality1 have no endpoint-level weight specified, so all endpoints within + // locality1 are equally weighted. assertThat(addr1.getAddresses()).isEqualTo(endpoint1.getAddresses()); assertThat(addr1.getAttributes().get(InternalXdsAttributes.ATTR_SERVER_WEIGHT)) - .isEqualTo(10 * 100); + .isEqualTo(10); assertThat(addr2.getAddresses()).isEqualTo(endpoint2.getAddresses()); assertThat(addr2.getAttributes().get(InternalXdsAttributes.ATTR_SERVER_WEIGHT)) + .isEqualTo(10); + assertThat(addr3.getAddresses()).isEqualTo(endpoint3.getAddresses()); + assertThat(addr3.getAttributes().get(InternalXdsAttributes.ATTR_SERVER_WEIGHT)) .isEqualTo(50 * 60); assertThat(childBalancer.name).isEqualTo(PRIORITY_POLICY_NAME); PriorityLbConfig priorityLbConfig = (PriorityLbConfig) childBalancer.config;