core: Remove LB refreshNameResolver check

It's been 17 months since the check was introduced, which is plenty for
the migration. Leaving ignoreRefreshNameResolutionCheck() in-place to
let users delete their call sites. We'll remove the method after a few
releases.

Fixes #9409
This commit is contained in:
Eric Anderson 2022-08-05 17:03:05 -07:00
parent 01aff58178
commit 2b50e405b1
6 changed files with 10 additions and 140 deletions

View File

@ -1073,8 +1073,10 @@ public abstract class LoadBalancer {
* that need to be updated for the new expected behavior. * that need to be updated for the new expected behavior.
* *
* @since 1.38.0 * @since 1.38.0
* @deprecated Warning has been removed
*/ */
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/8088") @ExperimentalApi("https://github.com/grpc/grpc-java/issues/8088")
@Deprecated
public void ignoreRefreshNameResolutionCheck() { public void ignoreRefreshNameResolutionCheck() {
// no-op // no-op
} }
@ -1356,13 +1358,19 @@ public abstract class LoadBalancer {
* unnecessary delays of RPCs. Please refer to {@link PickResult#withSubchannel * unnecessary delays of RPCs. Please refer to {@link PickResult#withSubchannel
* PickResult.withSubchannel()}'s javadoc for more information. * PickResult.withSubchannel()}'s javadoc for more information.
* *
* <p>When a subchannel's state is IDLE or TRANSIENT_FAILURE and the address for the subchannel
* was received in {@link LoadBalancer#handleResolvedAddresses}, load balancers should call
* {@link Helper#refreshNameResolution} to inform polling name resolvers that it is an
* appropriate time to refresh the addresses. Without the refresh, changes to the addresses may
* never be detected.
*
* <p>SHUTDOWN can only happen in two cases. One is that LoadBalancer called {@link * <p>SHUTDOWN can only happen in two cases. One is that LoadBalancer called {@link
* Subchannel#shutdown} earlier, thus it should have already discarded this Subchannel. The * Subchannel#shutdown} earlier, thus it should have already discarded this Subchannel. The
* other is that Channel is doing a {@link ManagedChannel#shutdownNow forced shutdown} or has * other is that Channel is doing a {@link ManagedChannel#shutdownNow forced shutdown} or has
* already terminated, thus there won't be further requests to LoadBalancer. Therefore, the * already terminated, thus there won't be further requests to LoadBalancer. Therefore, the
* LoadBalancer usually don't need to react to a SHUTDOWN state. * LoadBalancer usually don't need to react to a SHUTDOWN state.
* @param newState the new state
* *
* @param newState the new state
* @since 1.22.0 * @since 1.22.0
*/ */
void onSubchannelState(ConnectivityStateInfo newState); void onSubchannelState(ConnectivityStateInfo newState);

View File

@ -1453,8 +1453,6 @@ final class ManagedChannelImpl extends ManagedChannel implements
private final class LbHelperImpl extends LoadBalancer.Helper { private final class LbHelperImpl extends LoadBalancer.Helper {
AutoConfiguredLoadBalancer lb; AutoConfiguredLoadBalancer lb;
boolean nsRefreshedByLb;
boolean ignoreRefreshNsCheck;
@Override @Override
public AbstractSubchannel createSubchannel(CreateSubchannelArgs args) { public AbstractSubchannel createSubchannel(CreateSubchannelArgs args) {
@ -1493,7 +1491,6 @@ final class ManagedChannelImpl extends ManagedChannel implements
@Override @Override
public void refreshNameResolution() { public void refreshNameResolution() {
syncContext.throwIfNotInThisSynchronizationContext(); syncContext.throwIfNotInThisSynchronizationContext();
nsRefreshedByLb = true;
final class LoadBalancerRefreshNameResolution implements Runnable { final class LoadBalancerRefreshNameResolution implements Runnable {
@Override @Override
public void run() { public void run() {
@ -1504,11 +1501,6 @@ final class ManagedChannelImpl extends ManagedChannel implements
syncContext.execute(new LoadBalancerRefreshNameResolution()); syncContext.execute(new LoadBalancerRefreshNameResolution());
} }
@Override
public void ignoreRefreshNameResolutionCheck() {
ignoreRefreshNsCheck = true;
}
@Override @Override
public ManagedChannel createOobChannel(EquivalentAddressGroup addressGroup, String authority) { public ManagedChannel createOobChannel(EquivalentAddressGroup addressGroup, String authority) {
return createOobChannel(Collections.singletonList(addressGroup), authority); return createOobChannel(Collections.singletonList(addressGroup), authority);
@ -1979,16 +1971,6 @@ final class ManagedChannelImpl extends ManagedChannel implements
void onStateChange(InternalSubchannel is, ConnectivityStateInfo newState) { void onStateChange(InternalSubchannel is, ConnectivityStateInfo newState) {
checkState(listener != null, "listener is null"); checkState(listener != null, "listener is null");
listener.onSubchannelState(newState); listener.onSubchannelState(newState);
if (newState.getState() == TRANSIENT_FAILURE || newState.getState() == IDLE) {
if (!helper.ignoreRefreshNsCheck && !helper.nsRefreshedByLb) {
logger.log(Level.WARNING,
"LoadBalancer should call Helper.refreshNameResolution() to refresh name "
+ "resolution if subchannel state becomes TRANSIENT_FAILURE or IDLE. "
+ "This will no longer happen automatically in the future releases");
refreshAndResetNameResolution();
helper.nsRefreshedByLb = true;
}
}
} }
@Override @Override

View File

@ -95,6 +95,7 @@ public abstract class ForwardingLoadBalancerHelper extends LoadBalancer.Helper {
} }
@Override @Override
@Deprecated
public void ignoreRefreshNameResolutionCheck() { public void ignoreRefreshNameResolutionCheck() {
delegate().ignoreRefreshNameResolutionCheck(); delegate().ignoreRefreshNameResolutionCheck();
} }

View File

@ -140,9 +140,6 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import org.junit.After; import org.junit.After;
import org.junit.Assert; import org.junit.Assert;
@ -284,7 +281,6 @@ public class ManagedChannelImplTest {
private boolean requestConnection = true; private boolean requestConnection = true;
private BlockingQueue<MockClientTransportInfo> transports; private BlockingQueue<MockClientTransportInfo> transports;
private boolean panicExpected; private boolean panicExpected;
private final List<LogRecord> logs = new ArrayList<>();
@Captor @Captor
private ArgumentCaptor<ResolvedAddresses> resolvedAddressCaptor; private ArgumentCaptor<ResolvedAddresses> resolvedAddressCaptor;
@ -336,22 +332,6 @@ public class ManagedChannelImplTest {
when(executorPool.getObject()).thenReturn(executor.getScheduledExecutorService()); when(executorPool.getObject()).thenReturn(executor.getScheduledExecutorService());
when(balancerRpcExecutorPool.getObject()) when(balancerRpcExecutorPool.getObject())
.thenReturn(balancerRpcExecutor.getScheduledExecutorService()); .thenReturn(balancerRpcExecutor.getScheduledExecutorService());
Handler handler = new Handler() {
@Override
public void publish(LogRecord record) {
logs.add(record);
}
@Override
public void flush() {
}
@Override
public void close() throws SecurityException {
}
};
ManagedChannelImpl.logger.addHandler(handler);
ManagedChannelImpl.logger.setLevel(Level.ALL);
channelBuilder = new ManagedChannelImplBuilder(TARGET, channelBuilder = new ManagedChannelImplBuilder(TARGET,
new UnsupportedClientTransportFactoryBuilder(), new FixedPortProvider(DEFAULT_PORT)); new UnsupportedClientTransportFactoryBuilder(), new FixedPortProvider(DEFAULT_PORT));
@ -1591,103 +1571,6 @@ public class ManagedChannelImplTest {
timer.forwardTime(ManagedChannelImpl.SUBCHANNEL_SHUTDOWN_DELAY_SECONDS, TimeUnit.SECONDS); timer.forwardTime(ManagedChannelImpl.SUBCHANNEL_SHUTDOWN_DELAY_SECONDS, TimeUnit.SECONDS);
} }
@Test
public void subchannelConnectionBroken_noLbRefreshingResolver_logWarningAndTriggeRefresh() {
FakeNameResolverFactory nameResolverFactory =
new FakeNameResolverFactory.Builder(expectedUri)
.setServers(Collections.singletonList(new EquivalentAddressGroup(socketAddress)))
.build();
channelBuilder.nameResolverFactory(nameResolverFactory);
createChannel();
FakeNameResolverFactory.FakeNameResolver resolver =
Iterables.getOnlyElement(nameResolverFactory.resolvers);
assertThat(resolver.refreshCalled).isEqualTo(0);
Subchannel subchannel =
createSubchannelSafely(helper, addressGroup, Attributes.EMPTY, subchannelStateListener);
InternalSubchannel internalSubchannel =
(InternalSubchannel) subchannel.getInternalSubchannel();
internalSubchannel.obtainActiveTransport();
MockClientTransportInfo transportInfo = transports.poll();
// Break subchannel connection
transportInfo.listener.transportShutdown(Status.UNAVAILABLE.withDescription("unreachable"));
LogRecord log = Iterables.getOnlyElement(logs);
assertThat(log.getLevel()).isEqualTo(Level.WARNING);
assertThat(log.getMessage()).isEqualTo(
"LoadBalancer should call Helper.refreshNameResolution() to refresh name resolution if "
+ "subchannel state becomes TRANSIENT_FAILURE or IDLE. This will no longer happen "
+ "automatically in the future releases");
assertThat(resolver.refreshCalled).isEqualTo(1);
}
@Test
public void subchannelConnectionBroken_ResolverRefreshedByLb() {
FakeNameResolverFactory nameResolverFactory =
new FakeNameResolverFactory.Builder(expectedUri)
.setServers(Collections.singletonList(new EquivalentAddressGroup(socketAddress)))
.build();
channelBuilder.nameResolverFactory(nameResolverFactory);
createChannel();
FakeNameResolverFactory.FakeNameResolver resolver =
Iterables.getOnlyElement(nameResolverFactory.resolvers);
assertThat(resolver.refreshCalled).isEqualTo(0);
ArgumentCaptor<Helper> helperCaptor = ArgumentCaptor.forClass(Helper.class);
verify(mockLoadBalancerProvider).newLoadBalancer(helperCaptor.capture());
helper = helperCaptor.getValue();
SubchannelStateListener listener = new SubchannelStateListener() {
@Override
public void onSubchannelState(ConnectivityStateInfo newState) {
// Normal LoadBalancer should refresh name resolution when some subchannel enters
// TRANSIENT_FAILURE or IDLE
if (newState.getState() == TRANSIENT_FAILURE || newState.getState() == IDLE) {
helper.refreshNameResolution();
}
}
};
Subchannel subchannel =
createSubchannelSafely(helper, addressGroup, Attributes.EMPTY, listener);
InternalSubchannel internalSubchannel =
(InternalSubchannel) subchannel.getInternalSubchannel();
internalSubchannel.obtainActiveTransport();
MockClientTransportInfo transportInfo = transports.poll();
// Break subchannel connection and simulate load balancer refreshing name resolution
transportInfo.listener.transportShutdown(Status.UNAVAILABLE.withDescription("unreachable"));
assertThat(logs).isEmpty();
assertThat(resolver.refreshCalled).isEqualTo(1);
}
@Test
public void subchannelConnectionBroken_ignoreRefreshNameResolutionCheck_noRefresh() {
FakeNameResolverFactory nameResolverFactory =
new FakeNameResolverFactory.Builder(expectedUri)
.setServers(Collections.singletonList(new EquivalentAddressGroup(socketAddress)))
.build();
channelBuilder.nameResolverFactory(nameResolverFactory);
createChannel();
FakeNameResolverFactory.FakeNameResolver resolver =
Iterables.getOnlyElement(nameResolverFactory.resolvers);
assertThat(resolver.refreshCalled).isEqualTo(0);
ArgumentCaptor<Helper> helperCaptor = ArgumentCaptor.forClass(Helper.class);
verify(mockLoadBalancerProvider).newLoadBalancer(helperCaptor.capture());
helper = helperCaptor.getValue();
helper.ignoreRefreshNameResolutionCheck();
Subchannel subchannel =
createSubchannelSafely(helper, addressGroup, Attributes.EMPTY, subchannelStateListener);
InternalSubchannel internalSubchannel =
(InternalSubchannel) subchannel.getInternalSubchannel();
internalSubchannel.obtainActiveTransport();
MockClientTransportInfo transportInfo = transports.poll();
// Break subchannel connection
transportInfo.listener.transportShutdown(Status.UNAVAILABLE.withDescription("unreachable"));
assertThat(logs).isEmpty();
assertThat(resolver.refreshCalled).isEqualTo(0);
}
@Test @Test
public void subchannelStringableBeforeStart() { public void subchannelStringableBeforeStart() {
createChannel(); createChannel();

View File

@ -285,10 +285,8 @@ final class ClusterResolverLoadBalancer extends LoadBalancer {
private final class RefreshableHelper extends ForwardingLoadBalancerHelper { private final class RefreshableHelper extends ForwardingLoadBalancerHelper {
private final Helper delegate; private final Helper delegate;
@SuppressWarnings("deprecation")
private RefreshableHelper(Helper delegate) { private RefreshableHelper(Helper delegate) {
this.delegate = checkNotNull(delegate, "delegate"); this.delegate = checkNotNull(delegate, "delegate");
delegate.ignoreRefreshNameResolutionCheck();
} }
@Override @Override

View File

@ -679,7 +679,6 @@ public class ClusterResolverLoadBalancerTest {
EquivalentAddressGroup endpoint2 = makeAddress("endpoint-addr-2"); EquivalentAddressGroup endpoint2 = makeAddress("endpoint-addr-2");
resolver.deliverEndpointAddresses(Arrays.asList(endpoint1, endpoint2)); resolver.deliverEndpointAddresses(Arrays.asList(endpoint1, endpoint2));
assertThat(resolver.refreshCount).isEqualTo(0); assertThat(resolver.refreshCount).isEqualTo(0);
verify(helper).ignoreRefreshNameResolutionCheck();
FakeLoadBalancer childBalancer = Iterables.getOnlyElement(childBalancers); FakeLoadBalancer childBalancer = Iterables.getOnlyElement(childBalancers);
childBalancer.helper.refreshNameResolution(); childBalancer.helper.refreshNameResolution();
assertThat(resolver.refreshCount).isEqualTo(1); assertThat(resolver.refreshCount).isEqualTo(1);
@ -745,7 +744,6 @@ public class ClusterResolverLoadBalancerTest {
FakeLoadBalancer childBalancer = Iterables.getOnlyElement(childBalancers); FakeLoadBalancer childBalancer = Iterables.getOnlyElement(childBalancers);
assertAddressesEqual(Collections.singletonList(endpoint), childBalancer.addresses); assertAddressesEqual(Collections.singletonList(endpoint), childBalancer.addresses);
assertThat(resolver.refreshCount).isEqualTo(0); assertThat(resolver.refreshCount).isEqualTo(0);
verify(helper).ignoreRefreshNameResolutionCheck();
childBalancer.helper.refreshNameResolution(); childBalancer.helper.refreshNameResolution();
assertThat(resolver.refreshCount).isEqualTo(1); assertThat(resolver.refreshCount).isEqualTo(1);