core: ManagedChannelImpl to always use RetryingNameResolver (#10328)

ManagedCahnnelImpl did not make sure to use a RetryingNameResolver if
authority was not overriden. This was not a problem for DNS name
resolution as the DNS name resolver factory explicitly returns a
RetryingNameResolver. For polling name resolvers that do not do this in
their factories (like the grpclb name resolver) this meant not having retry
at all.
This commit is contained in:
Terry Wilson 2023-06-29 13:47:23 -07:00 committed by GitHub
parent 443a0502ba
commit 8192ff6103
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 24 additions and 15 deletions

View File

@ -749,9 +749,6 @@ final class ManagedChannelImpl extends ManagedChannel implements
String target, @Nullable final String overrideAuthority, String target, @Nullable final String overrideAuthority,
NameResolver.Factory nameResolverFactory, NameResolver.Args nameResolverArgs) { NameResolver.Factory nameResolverFactory, NameResolver.Args nameResolverArgs) {
NameResolver resolver = getNameResolver(target, nameResolverFactory, nameResolverArgs); NameResolver resolver = getNameResolver(target, nameResolverFactory, nameResolverArgs);
if (overrideAuthority == null) {
return resolver;
}
// If the nameResolver is not already a RetryingNameResolver, then wrap it with it. // If the nameResolver is not already a RetryingNameResolver, then wrap it with it.
// This helps guarantee that name resolution retry remains supported even as it has been // This helps guarantee that name resolution retry remains supported even as it has been
@ -769,6 +766,10 @@ final class ManagedChannelImpl extends ManagedChannel implements
nameResolverArgs.getSynchronizationContext()); nameResolverArgs.getSynchronizationContext());
} }
if (overrideAuthority == null) {
return usedNameResolver;
}
return new ForwardingNameResolver(usedNameResolver) { return new ForwardingNameResolver(usedNameResolver) {
@Override @Override
public String getServiceAuthority() { public String getServiceAuthority() {

View File

@ -139,8 +139,9 @@ public class ManagedChannelImplGetNameResolverTest {
private void testValidTarget(String target, String expectedUriString, URI expectedUri) { private void testValidTarget(String target, String expectedUriString, URI expectedUri) {
NameResolver.Factory nameResolverFactory = new FakeNameResolverFactory(expectedUri.getScheme()); NameResolver.Factory nameResolverFactory = new FakeNameResolverFactory(expectedUri.getScheme());
FakeNameResolver nameResolver = (FakeNameResolver) ManagedChannelImpl.getNameResolver( FakeNameResolver nameResolver
target, null, nameResolverFactory, NAMERESOLVER_ARGS); = (FakeNameResolver) ((RetryingNameResolver) ManagedChannelImpl.getNameResolver(
target, null, nameResolverFactory, NAMERESOLVER_ARGS)).getRetriedNameResolver();
assertNotNull(nameResolver); assertNotNull(nameResolver);
assertEquals(expectedUri, nameResolver.uri); assertEquals(expectedUri, nameResolver.uri);
assertEquals(expectedUriString, nameResolver.uri.toString()); assertEquals(expectedUriString, nameResolver.uri.toString());

View File

@ -280,6 +280,11 @@ public class ManagedChannelImplTest {
ArgumentCaptor.forClass(ClientStreamListener.class); ArgumentCaptor.forClass(ClientStreamListener.class);
private void createChannel(ClientInterceptor... interceptors) { private void createChannel(ClientInterceptor... interceptors) {
createChannel(false, interceptors);
}
private void createChannel(boolean nameResolutionExpectedToFail,
ClientInterceptor... interceptors) {
checkState(channel == null); checkState(channel == null);
channel = new ManagedChannelImpl( channel = new ManagedChannelImpl(
@ -288,7 +293,7 @@ public class ManagedChannelImplTest {
timer.getTimeProvider()); timer.getTimeProvider());
if (requestConnection) { if (requestConnection) {
int numExpectedTasks = 0; int numExpectedTasks = nameResolutionExpectedToFail ? 1 : 0;
// Force-exit the initial idle-mode // Force-exit the initial idle-mode
channel.syncContext.execute(new Runnable() { channel.syncContext.execute(new Runnable() {
@ -3000,7 +3005,7 @@ public class ManagedChannelImplTest {
FakeNameResolverFactory nameResolverFactory = FakeNameResolverFactory nameResolverFactory =
new FakeNameResolverFactory.Builder(expectedUri).setError(error).build(); new FakeNameResolverFactory.Builder(expectedUri).setError(error).build();
channelBuilder.nameResolverFactory(nameResolverFactory); channelBuilder.nameResolverFactory(nameResolverFactory);
createChannel(); createChannel(true);
assertThat(getStats(channel).channelTrace.events).contains(new ChannelTrace.Event.Builder() assertThat(getStats(channel).channelTrace.events).contains(new ChannelTrace.Event.Builder()
.setDescription("Failed to resolve name: " + error) .setDescription("Failed to resolve name: " + error)
@ -3503,10 +3508,11 @@ public class ManagedChannelImplTest {
ArgumentCaptor<Helper> helperCaptor = ArgumentCaptor.forClass(Helper.class); ArgumentCaptor<Helper> helperCaptor = ArgumentCaptor.forClass(Helper.class);
verify(mockLoadBalancerProvider).newLoadBalancer(helperCaptor.capture()); verify(mockLoadBalancerProvider).newLoadBalancer(helperCaptor.capture());
helper = helperCaptor.getValue(); helper = helperCaptor.getValue();
verify(mockLoadBalancer).acceptResolvedAddresses( verify(mockLoadBalancer).acceptResolvedAddresses(resolvedAddressCaptor.capture());
ResolvedAddresses.newBuilder() ResolvedAddresses resolvedAddresses = resolvedAddressCaptor.getValue();
.setAddresses(nameResolverFactory.servers) assertThat(resolvedAddresses.getAddresses()).isEqualTo(nameResolverFactory.servers);
.build()); assertThat(resolvedAddresses.getAttributes()
.get(RetryingNameResolver.RESOLUTION_RESULT_LISTENER_KEY)).isNotNull();
// simulating request connection and then transport ready after resolved address // simulating request connection and then transport ready after resolved address
Subchannel subchannel = Subchannel subchannel =
@ -3609,10 +3615,11 @@ public class ManagedChannelImplTest {
ArgumentCaptor<Helper> helperCaptor = ArgumentCaptor.forClass(Helper.class); ArgumentCaptor<Helper> helperCaptor = ArgumentCaptor.forClass(Helper.class);
verify(mockLoadBalancerProvider).newLoadBalancer(helperCaptor.capture()); verify(mockLoadBalancerProvider).newLoadBalancer(helperCaptor.capture());
helper = helperCaptor.getValue(); helper = helperCaptor.getValue();
verify(mockLoadBalancer).acceptResolvedAddresses( verify(mockLoadBalancer).acceptResolvedAddresses(resolvedAddressCaptor.capture());
ResolvedAddresses.newBuilder() ResolvedAddresses resolvedAddresses = resolvedAddressCaptor.getValue();
.setAddresses(nameResolverFactory.servers) assertThat(resolvedAddresses.getAddresses()).isEqualTo(nameResolverFactory.servers);
.build()); assertThat(resolvedAddresses.getAttributes()
.get(RetryingNameResolver.RESOLUTION_RESULT_LISTENER_KEY)).isNotNull();
// simulating request connection and then transport ready after resolved address // simulating request connection and then transport ready after resolved address
Subchannel subchannel = Subchannel subchannel =