Skip to content

Commit 03c49f7

Browse files
authored
grpclb: fallback timer only when not already using fallback backends. (#8646) (#8648)
Addresses a problem where we initially only resolve addresses to the backends, but not the load balancer and then later resolve addresses to both. In this situation the fallback timer was started during the second instance even if it resulted in the timer later failing as we were already using fallback backends. This change assures that a fallback time is only ever started if we are not already using the fallback backends. This is a follow-up fix to #8253.
1 parent c5fc08d commit 03c49f7

File tree

2 files changed

+30
-2
lines changed

2 files changed

+30
-2
lines changed

grpclb/src/main/java/io/grpc/grpclb/GrpclbState.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,9 @@ void handleAddresses(
287287
cancelLbRpcRetryTimer();
288288
startLbRpc();
289289
}
290-
// Start the fallback timer if it's never started
291-
if (fallbackTimer == null) {
290+
// Start the fallback timer if it's never started and we are not already using fallback
291+
// backends.
292+
if (fallbackTimer == null && !usingFallbackBackends) {
292293
fallbackTimer = syncContext.schedule(
293294
new FallbackModeTask(BALANCER_TIMEOUT_STATUS), FALLBACK_TIMEOUT_MS,
294295
TimeUnit.MILLISECONDS, timerService);

grpclb/src/test/java/io/grpc/grpclb/GrpclbLoadBalancerTest.java

+27
Original file line numberDiff line numberDiff line change
@@ -1462,6 +1462,33 @@ public void grpclbFallback_noBalancerAddress() {
14621462
.updateBalancingState(eq(TRANSIENT_FAILURE), any(SubchannelPicker.class));
14631463
}
14641464

1465+
/**
1466+
* A test for a situation where we first only get backend addresses resolved and then in a
1467+
* later name resolution get both backend and load balancer addresses. The first instance
1468+
* will switch us to using fallback backends and it is important that in the second instance
1469+
* we do not start a fallback timer as it will fail when it triggers if the fallback backends
1470+
* are already in use.
1471+
*/
1472+
@Test
1473+
public void grpclbFallback_noTimerWhenAlreadyInFallback() {
1474+
// Initially we only get backend addresses without any LB ones. This should get us to use
1475+
// fallback backends from the start as we won't be able to even talk to the load balancer.
1476+
// No fallback timer would be started as we already started to use fallback backends.
1477+
deliverResolvedAddresses(createResolvedBalancerAddresses(1),
1478+
Collections.<EquivalentAddressGroup>emptyList());
1479+
assertEquals(0, fakeClock.numPendingTasks(FALLBACK_MODE_TASK_FILTER));
1480+
1481+
// Later a new name resolution call happens and we get both backend and LB addresses. Since we
1482+
// are already operating with fallback backends a fallback timer should not be started to move
1483+
// us to fallback mode.
1484+
deliverResolvedAddresses(Collections.<EquivalentAddressGroup>emptyList(),
1485+
createResolvedBalancerAddresses(1));
1486+
1487+
// If a fallback timer is started it will eventually throw an exception when it tries to switch
1488+
// us to using fallback backends when we already are using them.
1489+
assertEquals(0, fakeClock.numPendingTasks(FALLBACK_MODE_TASK_FILTER));
1490+
}
1491+
14651492
@Test
14661493
public void grpclbFallback_balancerLost() {
14671494
subtestGrpclbFallbackConnectionLost(true, false);

0 commit comments

Comments
 (0)