core: Apply RetryingNameResolver in ManagedChannelImpl (#10371)

Wrapping the DnsNameResolver in DnsNameResolverProvider can cause
problems to external name resolvers that delegate to a DnsResolver
already wrapped in RetryingNameResolver. ManagedChannelImpl would
end up wrapping these name resolvers again, causing an exception
later from a RetryingNameResolver safeguard that checks for double
wrapping.
This commit is contained in:
Terry Wilson 2023-07-12 10:14:50 -07:00 committed by GitHub
parent 4fa2814d65
commit 78cf1c39cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 15 additions and 37 deletions

View File

@ -56,19 +56,13 @@ public final class DnsNameResolverProvider extends NameResolverProvider {
Preconditions.checkArgument(targetPath.startsWith("/"), Preconditions.checkArgument(targetPath.startsWith("/"),
"the path component (%s) of the target (%s) must start with '/'", targetPath, targetUri); "the path component (%s) of the target (%s) must start with '/'", targetPath, targetUri);
String name = targetPath.substring(1); String name = targetPath.substring(1);
return new RetryingNameResolver( return new DnsNameResolver(
new DnsNameResolver(
targetUri.getAuthority(), targetUri.getAuthority(),
name, name,
args, args,
GrpcUtil.SHARED_CHANNEL_EXECUTOR, GrpcUtil.SHARED_CHANNEL_EXECUTOR,
Stopwatch.createUnstarted(), Stopwatch.createUnstarted(),
IS_ANDROID), IS_ANDROID);
new BackoffPolicyRetryScheduler(
new ExponentialBackoffPolicy.Provider(),
args.getScheduledExecutorService(),
args.getSynchronizationContext()),
args.getSynchronizationContext());
} else { } else {
return null; return null;
} }

View File

@ -750,21 +750,14 @@ final class ManagedChannelImpl extends ManagedChannel implements
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 the nameResolver is not already a RetryingNameResolver, then wrap it with it. // We wrap the name resolver in a RetryingNameResolver to give it the ability to retry failures.
// This helps guarantee that name resolution retry remains supported even as it has been
// removed from ManagedChannelImpl.
// TODO: After a transition period, all NameResolver implementations that need retry should use // TODO: After a transition period, all NameResolver implementations that need retry should use
// RetryingNameResolver directly and this step can be removed. // RetryingNameResolver directly and this step can be removed.
NameResolver usedNameResolver; NameResolver usedNameResolver = new RetryingNameResolver(resolver,
if (resolver instanceof RetryingNameResolver) {
usedNameResolver = resolver;
} else {
usedNameResolver = new RetryingNameResolver(resolver,
new BackoffPolicyRetryScheduler(new ExponentialBackoffPolicy.Provider(), new BackoffPolicyRetryScheduler(new ExponentialBackoffPolicy.Provider(),
nameResolverArgs.getScheduledExecutorService(), nameResolverArgs.getScheduledExecutorService(),
nameResolverArgs.getSynchronizationContext()), nameResolverArgs.getSynchronizationContext()),
nameResolverArgs.getSynchronizationContext()); nameResolverArgs.getSynchronizationContext());
}
if (overrideAuthority == null) { if (overrideAuthority == null) {
return usedNameResolver; return usedNameResolver;

View File

@ -61,9 +61,7 @@ public class DnsNameResolverProviderTest {
@Test @Test
public void newNameResolver() { public void newNameResolver() {
assertSame(DnsNameResolver.class, assertSame(DnsNameResolver.class,
((RetryingNameResolver) provider.newNameResolver( provider.newNameResolver(URI.create("dns:///localhost:443"), args).getClass());
URI.create("dns:///localhost:443"), args))
.getRetriedNameResolver().getClass());
assertNull( assertNull(
provider.newNameResolver(URI.create("notdns:///localhost:443"), args)); provider.newNameResolver(URI.create("notdns:///localhost:443"), args));
} }

View File

@ -1293,8 +1293,7 @@ public class DnsNameResolverTest {
} }
private void testValidUri(URI uri, String exportedAuthority, int expectedPort) { private void testValidUri(URI uri, String exportedAuthority, int expectedPort) {
DnsNameResolver resolver = (DnsNameResolver) ((RetryingNameResolver) provider.newNameResolver( DnsNameResolver resolver = (DnsNameResolver) provider.newNameResolver(uri, args);
uri, args)).getRetriedNameResolver();
assertNotNull(resolver); assertNotNull(resolver);
assertEquals(expectedPort, resolver.getPort()); assertEquals(expectedPort, resolver.getPort());
assertEquals(exportedAuthority, resolver.getServiceAuthority()); assertEquals(exportedAuthority, resolver.getServiceAuthority());

View File

@ -542,7 +542,7 @@ public class ServiceConfigErrorHandlingTest {
final URI expectedUri; final URI expectedUri;
final List<EquivalentAddressGroup> servers; final List<EquivalentAddressGroup> servers;
final boolean resolvedAtStart; final boolean resolvedAtStart;
final ArrayList<RetryingNameResolver> resolvers = new ArrayList<>(); final ArrayList<FakeNameResolver> resolvers = new ArrayList<>();
final AtomicReference<Map<String, ?>> nextRawServiceConfig = new AtomicReference<>(); final AtomicReference<Map<String, ?>> nextRawServiceConfig = new AtomicReference<>();
final AtomicReference<Attributes> nextAttributes = new AtomicReference<>(Attributes.EMPTY); final AtomicReference<Attributes> nextAttributes = new AtomicReference<>(Attributes.EMPTY);
@ -561,13 +561,7 @@ public class ServiceConfigErrorHandlingTest {
return null; return null;
} }
assertEquals(DEFAULT_PORT, args.getDefaultPort()); assertEquals(DEFAULT_PORT, args.getDefaultPort());
RetryingNameResolver resolver = new RetryingNameResolver( FakeNameResolver resolver = new FakeNameResolver(args.getServiceConfigParser());
new FakeNameResolver(args.getServiceConfigParser()),
new BackoffPolicyRetryScheduler(
new FakeBackoffPolicyProvider(),
args.getScheduledExecutorService(),
args.getSynchronizationContext()),
args.getSynchronizationContext());
resolvers.add(resolver); resolvers.add(resolver);
return resolver; return resolver;
} }
@ -578,8 +572,8 @@ public class ServiceConfigErrorHandlingTest {
} }
void allResolved() { void allResolved() {
for (RetryingNameResolver resolver : resolvers) { for (FakeNameResolver resolver : resolvers) {
((FakeNameResolver)resolver.getRetriedNameResolver()).resolved(); resolver.resolved();
} }
} }