Skip to content

Commit 3753a4c

Browse files
authored
grpclb: fallback timer only when not already using fallback backends. (#8646) (#8654)
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 0006c69 commit 3753a4c

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
@@ -282,8 +282,9 @@ void handleAddresses(
282282
cancelLbRpcRetryTimer();
283283
startLbRpc();
284284
}
285-
// Start the fallback timer if it's never started
286-
if (fallbackTimer == null) {
285+
// Start the fallback timer if it's never started and we are not already using fallback
286+
// backends.
287+
if (fallbackTimer == null && !usingFallbackBackends) {
287288
fallbackTimer = syncContext.schedule(
288289
new FallbackModeTask(BALANCER_TIMEOUT_STATUS), FALLBACK_TIMEOUT_MS,
289290
TimeUnit.MILLISECONDS, timerService);

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

+27
Original file line numberDiff line numberDiff line change
@@ -1520,6 +1520,33 @@ public void grpclbFallback_noBalancerAddress() {
15201520
.updateBalancingState(eq(TRANSIENT_FAILURE), any(SubchannelPicker.class));
15211521
}
15221522

1523+
/**
1524+
* A test for a situation where we first only get backend addresses resolved and then in a
1525+
* later name resolution get both backend and load balancer addresses. The first instance
1526+
* will switch us to using fallback backends and it is important that in the second instance
1527+
* we do not start a fallback timer as it will fail when it triggers if the fallback backends
1528+
* are already in use.
1529+
*/
1530+
@Test
1531+
public void grpclbFallback_noTimerWhenAlreadyInFallback() {
1532+
// Initially we only get backend addresses without any LB ones. This should get us to use
1533+
// fallback backends from the start as we won't be able to even talk to the load balancer.
1534+
// No fallback timer would be started as we already started to use fallback backends.
1535+
deliverResolvedAddresses(createResolvedBalancerAddresses(1),
1536+
Collections.<EquivalentAddressGroup>emptyList());
1537+
assertEquals(0, fakeClock.numPendingTasks(FALLBACK_MODE_TASK_FILTER));
1538+
1539+
// Later a new name resolution call happens and we get both backend and LB addresses. Since we
1540+
// are already operating with fallback backends a fallback timer should not be started to move
1541+
// us to fallback mode.
1542+
deliverResolvedAddresses(Collections.<EquivalentAddressGroup>emptyList(),
1543+
createResolvedBalancerAddresses(1));
1544+
1545+
// If a fallback timer is started it will eventually throw an exception when it tries to switch
1546+
// us to using fallback backends when we already are using them.
1547+
assertEquals(0, fakeClock.numPendingTasks(FALLBACK_MODE_TASK_FILTER));
1548+
}
1549+
15231550
@Test
15241551
public void grpclbFallback_balancerLost() {
15251552
subtestGrpclbFallbackConnectionLost(true, false);

0 commit comments

Comments
 (0)