Skip to content

Commit 9287f85

Browse files
committed
Fix grpclb incompatibility
gRPC-LB's tests failed when using FixedResultPicker because it didn't transition to READY. This was because GrpclbState.maybeUpdatePicker() didn't consider the ConnectivityState when checking if anything had changed. The old PickFirstLoadBalancer.Picker didn't implement equals() so every update was considered different, ignoring the connectivity state. PickFirstLeafLoadBalancer wasn't impacted because it didn't pick a subchannel when in CONNECTING, and neither did PickFirstLoadBalancer after the first update. This is fixed on both sides: PickFirstLoadBalancer no londer returns the useless subchannel when picking during CONNECTING, and gRPC-LB now checks the connectivity state. This now causes what appears to be a bug in RLS. That is still being investigated.
1 parent 842c53f commit 9287f85

File tree

3 files changed

+10
-9
lines changed

3 files changed

+10
-9
lines changed

core/src/main/java/io/grpc/internal/PickFirstLoadBalancer.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,7 @@ public void onSubchannelState(ConnectivityStateInfo stateInfo) {
8686

8787
// The channel state does not get updated when doing name resolving today, so for the moment
8888
// let LB report CONNECTION and call subchannel.requestConnection() immediately.
89-
updateBalancingState(
90-
CONNECTING, new FixedResultPicker(PickResult.withSubchannel(subchannel)));
89+
updateBalancingState(CONNECTING, new FixedResultPicker(PickResult.withNoResult()));
9190
subchannel.requestConnection();
9291
} else {
9392
subchannel.updateAddresses(servers);

core/src/test/java/io/grpc/internal/PickFirstLoadBalancerTest.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ public void refreshNameResolutionAfterSubchannelConnectionBroken() {
219219
inOrder.verify(mockSubchannel).start(stateListenerCaptor.capture());
220220
SubchannelStateListener stateListener = stateListenerCaptor.getValue();
221221
inOrder.verify(mockHelper).updateBalancingState(eq(CONNECTING), pickerCaptor.capture());
222-
assertSame(mockSubchannel, pickerCaptor.getValue().pickSubchannel(mockArgs).getSubchannel());
222+
assertThat(pickerCaptor.getValue().pickSubchannel(mockArgs).hasResult()).isFalse();
223223
inOrder.verify(mockSubchannel).requestConnection();
224224

225225
stateListener.onSubchannelState(ConnectivityStateInfo.forNonError(CONNECTING));
@@ -278,7 +278,7 @@ public void pickAfterResolvedAndChanged() throws Exception {
278278
assertThat(args.getAddresses()).isEqualTo(servers);
279279
inOrder.verify(mockHelper).updateBalancingState(eq(CONNECTING), pickerCaptor.capture());
280280
verify(mockSubchannel).requestConnection();
281-
assertEquals(mockSubchannel, pickerCaptor.getValue().pickSubchannel(mockArgs).getSubchannel());
281+
assertThat(pickerCaptor.getValue().pickSubchannel(mockArgs).hasResult()).isFalse();
282282

283283
loadBalancer.acceptResolvedAddresses(
284284
ResolvedAddresses.newBuilder().setAddresses(newServers).setAttributes(affinity).build());
@@ -300,7 +300,7 @@ public void pickAfterStateChangeAfterResolution() throws Exception {
300300
verify(mockSubchannel).start(stateListenerCaptor.capture());
301301
SubchannelStateListener stateListener = stateListenerCaptor.getValue();
302302
verify(mockHelper).updateBalancingState(eq(CONNECTING), pickerCaptor.capture());
303-
Subchannel subchannel = pickerCaptor.getValue().pickSubchannel(mockArgs).getSubchannel();
303+
assertThat(pickerCaptor.getValue().pickSubchannel(mockArgs).hasResult()).isFalse();
304304
reset(mockHelper);
305305
when(mockHelper.getSynchronizationContext()).thenReturn(syncContext);
306306

@@ -317,7 +317,7 @@ public void pickAfterStateChangeAfterResolution() throws Exception {
317317

318318
stateListener.onSubchannelState(ConnectivityStateInfo.forNonError(READY));
319319
inOrder.verify(mockHelper).updateBalancingState(eq(READY), pickerCaptor.capture());
320-
assertEquals(subchannel, pickerCaptor.getValue().pickSubchannel(mockArgs).getSubchannel());
320+
assertEquals(mockSubchannel, pickerCaptor.getValue().pickSubchannel(mockArgs).getSubchannel());
321321

322322
verify(mockHelper, atLeast(0)).getSynchronizationContext(); // Don't care
323323
verifyNoMoreInteractions(mockHelper);
@@ -405,8 +405,7 @@ public void nameResolutionSuccessAfterError() throws Exception {
405405
inOrder.verify(mockHelper).updateBalancingState(eq(CONNECTING), pickerCaptor.capture());
406406
verify(mockSubchannel).requestConnection();
407407

408-
assertEquals(mockSubchannel, pickerCaptor.getValue().pickSubchannel(mockArgs)
409-
.getSubchannel());
408+
assertThat(pickerCaptor.getValue().pickSubchannel(mockArgs).hasResult()).isFalse();
410409

411410
assertEquals(pickerCaptor.getValue().pickSubchannel(mockArgs),
412411
pickerCaptor.getValue().pickSubchannel(mockArgs));

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ enum Mode {
187187
private List<DropEntry> dropList = Collections.emptyList();
188188
// Contains only non-drop, i.e., backends from the round-robin list from the balancer.
189189
private List<BackendEntry> backendList = Collections.emptyList();
190+
private ConnectivityState currentState = ConnectivityState.CONNECTING;
190191
private RoundRobinPicker currentPicker =
191192
new RoundRobinPicker(Collections.<DropEntry>emptyList(), Arrays.asList(BUFFER_ENTRY));
192193
private boolean requestConnectionPending;
@@ -937,10 +938,12 @@ private void maybeUpdatePicker(ConnectivityState state, RoundRobinPicker picker)
937938
// Discard the new picker if we are sure it won't make any difference, in order to save
938939
// re-processing pending streams, and avoid unnecessary resetting of the pointer in
939940
// RoundRobinPicker.
940-
if (picker.dropList.equals(currentPicker.dropList)
941+
if (state.equals(currentState)
942+
&& picker.dropList.equals(currentPicker.dropList)
941943
&& picker.pickList.equals(currentPicker.pickList)) {
942944
return;
943945
}
946+
currentState = state;
944947
currentPicker = picker;
945948
helper.updateBalancingState(state, picker);
946949
}

0 commit comments

Comments
 (0)