From 603b7712ee3d768312e214b7862c7ced1ad77c11 Mon Sep 17 00:00:00 2001 From: Kun Zhang Date: Thu, 7 Mar 2019 15:08:24 -0800 Subject: [PATCH] grpclb: use fallback addresses if no balancer address is given --- .../main/java/io/grpc/grpclb/GrpclbState.java | 36 ++++++++++--------- .../grpc/grpclb/GrpclbLoadBalancerTest.java | 26 ++++++++++++++ 2 files changed, 45 insertions(+), 17 deletions(-) diff --git a/grpclb/src/main/java/io/grpc/grpclb/GrpclbState.java b/grpclb/src/main/java/io/grpc/grpclb/GrpclbState.java index bc647504a5a..c59ecbd3b47 100644 --- a/grpclb/src/main/java/io/grpc/grpclb/GrpclbState.java +++ b/grpclb/src/main/java/io/grpc/grpclb/GrpclbState.java @@ -193,25 +193,27 @@ void handleSubchannelState(Subchannel subchannel, ConnectivityStateInfo newState void handleAddresses( List newLbAddressGroups, List newBackendServers) { if (newLbAddressGroups.isEmpty()) { - propagateError(Status.UNAVAILABLE.withDescription( - "NameResolver returned no LB address while asking for GRPCLB")); - return; - } - LbAddressGroup newLbAddressGroup = flattenLbAddressGroups(newLbAddressGroups); - startLbComm(newLbAddressGroup); - // Avoid creating a new RPC just because the addresses were updated, as it can cause a - // stampeding herd. The current RPC may be on a connection to an address not present in - // newLbAddressGroups, but we're considering that "okay". If we detected the RPC is to an - // outdated backend, we could choose to re-create the RPC. - if (lbStream == null) { - startLbRpc(); + // No balancer address: close existing balancer connection and enter fallback mode + // immediately. + shutdownLbComm(); + syncContext.execute(new FallbackModeTask()); + } else { + LbAddressGroup newLbAddressGroup = flattenLbAddressGroups(newLbAddressGroups); + startLbComm(newLbAddressGroup); + // Avoid creating a new RPC just because the addresses were updated, as it can cause a + // stampeding herd. The current RPC may be on a connection to an address not present in + // newLbAddressGroups, but we're considering that "okay". If we detected the RPC is to an + // outdated backend, we could choose to re-create the RPC. + if (lbStream == null) { + startLbRpc(); + } + // Start the fallback timer if it's never started + if (fallbackTimer == null) { + fallbackTimer = syncContext.schedule( + new FallbackModeTask(), FALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS, timerService); + } } fallbackBackendList = newBackendServers; - // Start the fallback timer if it's never started - if (fallbackTimer == null) { - fallbackTimer = syncContext.schedule( - new FallbackModeTask(), FALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS, timerService); - } if (usingFallbackBackends) { // Populate the new fallback backends to round-robin list. useFallbackBackends(); diff --git a/grpclb/src/test/java/io/grpc/grpclb/GrpclbLoadBalancerTest.java b/grpclb/src/test/java/io/grpc/grpclb/GrpclbLoadBalancerTest.java index 8d2645436a9..417e0408e64 100644 --- a/grpclb/src/test/java/io/grpc/grpclb/GrpclbLoadBalancerTest.java +++ b/grpclb/src/test/java/io/grpc/grpclb/GrpclbLoadBalancerTest.java @@ -32,6 +32,7 @@ import static org.junit.Assert.assertTrue; import static org.mockito.AdditionalAnswers.delegatesTo; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Matchers.same; import static org.mockito.Mockito.atLeast; @@ -1388,6 +1389,31 @@ public void grpclbFallback_breakLbStreamBeforeFallbackTimerExpires() { .build())); } + @Test + public void grpclbFallback_noBalancerAddress() { + long loadReportIntervalMillis = 1983; + InOrder inOrder = inOrder(helper, subchannelPool); + + // Create a resolution list with just backend addresses + List resolutionList = createResolvedServerAddresses(false, false); + Attributes resolutionAttrs = Attributes.EMPTY; + deliverResolvedAddresses(resolutionList, resolutionAttrs); + + assertThat(logs).containsExactly( + "INFO: Using fallback backends", + "INFO: Using RR list=[[[FakeSocketAddress-fake-address-0]/{}], " + + "[[FakeSocketAddress-fake-address-1]/{}]], drop=[null, null]", + "INFO: CONNECTING: picks=[BUFFER_ENTRY], drops=[null, null]").inOrder(); + + // Fall back to the backends from resolver + fallbackTestVerifyUseOfFallbackBackendLists(inOrder, resolutionList); + + // No fallback timeout timer scheduled. + assertEquals(0, fakeClock.numPendingTasks(FALLBACK_MODE_TASK_FILTER)); + verify(helper, never()) + .createOobChannel(any(EquivalentAddressGroup.class), anyString()); + } + @Test public void grpclbFallback_balancerLost() { subtestGrpclbFallbackConnectionLost(true, false);