Revert "core: DnsNameResolver caches refresh (#4812)"

This reverts commit 189991012b.
This commit is contained in:
Jihun Cho 2018-10-12 15:10:33 -07:00 committed by creamsoup
parent c24f2fd25b
commit 0e8cf58d1a
3 changed files with 8 additions and 232 deletions

View File

@ -20,7 +20,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.base.Stopwatch;
import com.google.common.base.Verify; import com.google.common.base.Verify;
import io.grpc.Attributes; import io.grpc.Attributes;
import io.grpc.EquivalentAddressGroup; import io.grpc.EquivalentAddressGroup;
@ -43,7 +42,6 @@ import java.util.Map.Entry;
import java.util.Random; import java.util.Random;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -90,19 +88,6 @@ final class DnsNameResolver extends NameResolver {
private static final String JNDI_TXT_PROPERTY = private static final String JNDI_TXT_PROPERTY =
System.getProperty("io.grpc.internal.DnsNameResolverProvider.enable_service_config", "false"); System.getProperty("io.grpc.internal.DnsNameResolverProvider.enable_service_config", "false");
/**
* Java networking system properties name for caching DNS result.
*
* <p>Default value is -1 (cache forever) if security manager is installed. If security manager is
* not installed, the ttl value is {@code null} which falls back to {@link
* #DEFAULT_NETWORK_CACHE_TTL_SECONDS gRPC default value}.
*/
@VisibleForTesting
static final String NETWORKADDRESS_CACHE_TTL_PROPERTY = "networkaddress.cache.ttl";
/** Default DNS cache duration if network cache ttl value is not specified ({@code null}). */
@VisibleForTesting
static final long DEFAULT_NETWORK_CACHE_TTL_SECONDS = 30;
@VisibleForTesting @VisibleForTesting
static boolean enableJndi = Boolean.parseBoolean(JNDI_PROPERTY); static boolean enableJndi = Boolean.parseBoolean(JNDI_PROPERTY);
@VisibleForTesting @VisibleForTesting
@ -130,8 +115,6 @@ final class DnsNameResolver extends NameResolver {
private final String host; private final String host;
private final int port; private final int port;
private final Resource<ExecutorService> executorResource; private final Resource<ExecutorService> executorResource;
private final long networkAddressCacheTtlNanos;
private final Stopwatch stopwatch;
@GuardedBy("this") @GuardedBy("this")
private boolean shutdown; private boolean shutdown;
@GuardedBy("this") @GuardedBy("this")
@ -140,11 +123,10 @@ final class DnsNameResolver extends NameResolver {
private boolean resolving; private boolean resolving;
@GuardedBy("this") @GuardedBy("this")
private Listener listener; private Listener listener;
private ResolutionResults cachedResolutionResults;
DnsNameResolver(@Nullable String nsAuthority, String name, Attributes params, DnsNameResolver(@Nullable String nsAuthority, String name, Attributes params,
Resource<ExecutorService> executorResource, ProxyDetector proxyDetector, Resource<ExecutorService> executorResource,
Stopwatch stopwatch) { ProxyDetector proxyDetector) {
// TODO: if a DNS server is provided as nsAuthority, use it. // TODO: if a DNS server is provided as nsAuthority, use it.
// https://www.captechconsulting.com/blogs/accessing-the-dusty-corners-of-dns-with-java // https://www.captechconsulting.com/blogs/accessing-the-dusty-corners-of-dns-with-java
this.executorResource = executorResource; this.executorResource = executorResource;
@ -167,8 +149,6 @@ final class DnsNameResolver extends NameResolver {
port = nameUri.getPort(); port = nameUri.getPort();
} }
this.proxyDetector = proxyDetector; this.proxyDetector = proxyDetector;
this.stopwatch = Preconditions.checkNotNull(stopwatch, "stopwatch");
this.networkAddressCacheTtlNanos = getNetworkAddressCacheTtlNanos();
} }
@Override @Override
@ -198,13 +178,6 @@ final class DnsNameResolver extends NameResolver {
if (shutdown) { if (shutdown) {
return; return;
} }
boolean resourceRefreshRequired = cachedResolutionResults == null
|| networkAddressCacheTtlNanos == 0
|| (networkAddressCacheTtlNanos > 0
&& stopwatch.elapsed(TimeUnit.NANOSECONDS) > networkAddressCacheTtlNanos);
if (!resourceRefreshRequired) {
return;
}
savedListener = listener; savedListener = listener;
resolving = true; resolving = true;
} }
@ -234,10 +207,6 @@ final class DnsNameResolver extends NameResolver {
} }
resolutionResults = resolutionResults =
resolveAll(addressResolver, resourceResolver, enableSrv, enableTxt, host); resolveAll(addressResolver, resourceResolver, enableSrv, enableTxt, host);
cachedResolutionResults = resolutionResults;
if (networkAddressCacheTtlNanos > 0) {
stopwatch.reset().start();
}
} catch (Exception e) { } catch (Exception e) {
savedListener.onError( savedListener.onError(
Status.UNAVAILABLE.withDescription("Unable to resolve host " + host).withCause(e)); Status.UNAVAILABLE.withDescription("Unable to resolve host " + host).withCause(e));
@ -284,23 +253,6 @@ final class DnsNameResolver extends NameResolver {
} }
}; };
/** Returns value of network address cache ttl property. */
private static long getNetworkAddressCacheTtlNanos() {
String cacheTtlPropertyValue = System.getProperty(NETWORKADDRESS_CACHE_TTL_PROPERTY);
long cacheTtl = DEFAULT_NETWORK_CACHE_TTL_SECONDS;
if (cacheTtlPropertyValue != null) {
try {
cacheTtl = Long.parseLong(cacheTtlPropertyValue);
} catch (NumberFormatException e) {
logger.log(
Level.WARNING,
"Property({0}) valid is not valid number format({1}), fall back to default({2})",
new Object[] {NETWORKADDRESS_CACHE_TTL_PROPERTY, cacheTtlPropertyValue, cacheTtl});
}
}
return cacheTtl > 0 ? TimeUnit.SECONDS.toNanos(cacheTtl) : cacheTtl;
}
@GuardedBy("this") @GuardedBy("this")
private void resolve() { private void resolve() {
if (resolving || shutdown) { if (resolving || shutdown) {

View File

@ -17,7 +17,6 @@
package io.grpc.internal; package io.grpc.internal;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.base.Stopwatch;
import io.grpc.Attributes; import io.grpc.Attributes;
import io.grpc.NameResolverProvider; import io.grpc.NameResolverProvider;
import java.net.URI; import java.net.URI;
@ -53,8 +52,7 @@ public final class DnsNameResolverProvider extends NameResolverProvider {
name, name,
params, params,
GrpcUtil.SHARED_CHANNEL_EXECUTOR, GrpcUtil.SHARED_CHANNEL_EXECUTOR,
GrpcUtil.getDefaultProxyDetector(), GrpcUtil.getDefaultProxyDetector());
Stopwatch.createUnstarted());
} else { } else {
return null; return null;
} }

View File

@ -27,13 +27,10 @@ import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import com.google.common.base.Stopwatch;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.net.InetAddresses; import com.google.common.net.InetAddresses;
import com.google.common.testing.FakeTicker;
import io.grpc.Attributes; import io.grpc.Attributes;
import io.grpc.EquivalentAddressGroup; import io.grpc.EquivalentAddressGroup;
import io.grpc.NameResolver; import io.grpc.NameResolver;
@ -55,8 +52,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
@ -108,25 +103,21 @@ public class DnsNameResolverTest {
private NameResolver.Listener mockListener; private NameResolver.Listener mockListener;
@Captor @Captor
private ArgumentCaptor<List<EquivalentAddressGroup>> resultCaptor; private ArgumentCaptor<List<EquivalentAddressGroup>> resultCaptor;
@Nullable
private String networkaddressCacheTtlPropertyValue;
private DnsNameResolver newResolver(String name, int port) { private DnsNameResolver newResolver(String name, int port) {
return newResolver(name, port, GrpcUtil.NOOP_PROXY_DETECTOR, Stopwatch.createUnstarted()); return newResolver(name, port, GrpcUtil.NOOP_PROXY_DETECTOR);
} }
private DnsNameResolver newResolver( private DnsNameResolver newResolver(
String name, String name,
int port, int port,
ProxyDetector proxyDetector, ProxyDetector proxyDetector) {
Stopwatch stopwatch) {
DnsNameResolver dnsResolver = new DnsNameResolver( DnsNameResolver dnsResolver = new DnsNameResolver(
null, null,
name, name,
Attributes.newBuilder().set(NameResolver.Factory.PARAMS_DEFAULT_PORT, port).build(), Attributes.newBuilder().set(NameResolver.Factory.PARAMS_DEFAULT_PORT, port).build(),
fakeExecutorResource, fakeExecutorResource,
proxyDetector, proxyDetector);
stopwatch);
return dnsResolver; return dnsResolver;
} }
@ -134,19 +125,6 @@ public class DnsNameResolverTest {
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
DnsNameResolver.enableJndi = true; DnsNameResolver.enableJndi = true;
networkaddressCacheTtlPropertyValue =
System.getProperty(DnsNameResolver.NETWORKADDRESS_CACHE_TTL_PROPERTY);
}
@After
public void restoreSystemProperty() {
if (networkaddressCacheTtlPropertyValue == null) {
System.clearProperty(DnsNameResolver.NETWORKADDRESS_CACHE_TTL_PROPERTY);
} else {
System.setProperty(
DnsNameResolver.NETWORKADDRESS_CACHE_TTL_PROPERTY,
networkaddressCacheTtlPropertyValue);
}
} }
@After @After
@ -198,8 +176,7 @@ public class DnsNameResolverTest {
} }
@Test @Test
public void resolve_neverCache() throws Exception { public void resolve() throws Exception {
System.setProperty(DnsNameResolver.NETWORKADDRESS_CACHE_TTL_PROPERTY, "0");
final List<InetAddress> answer1 = createAddressList(2); final List<InetAddress> answer1 = createAddressList(2);
final List<InetAddress> answer2 = createAddressList(1); final List<InetAddress> answer2 = createAddressList(1);
String name = "foo.googleapis.com"; String name = "foo.googleapis.com";
@ -226,156 +203,6 @@ public class DnsNameResolverTest {
verify(mockResolver, times(2)).resolveAddress(Matchers.anyString()); verify(mockResolver, times(2)).resolveAddress(Matchers.anyString());
} }
@Test
public void resolve_cacheForever() throws Exception {
System.setProperty(DnsNameResolver.NETWORKADDRESS_CACHE_TTL_PROPERTY, "-1");
final List<InetAddress> answer1 = createAddressList(2);
String name = "foo.googleapis.com";
FakeTicker fakeTicker = new FakeTicker();
DnsNameResolver resolver =
newResolver(name, 81, GrpcUtil.NOOP_PROXY_DETECTOR, Stopwatch.createUnstarted(fakeTicker));
AddressResolver mockResolver = mock(AddressResolver.class);
when(mockResolver.resolveAddress(Matchers.anyString()))
.thenReturn(answer1)
.thenThrow(new AssertionError("should not called twice"));
resolver.setAddressResolver(mockResolver);
resolver.start(mockListener);
assertEquals(1, fakeExecutor.runDueTasks());
verify(mockListener).onAddresses(resultCaptor.capture(), any(Attributes.class));
assertAnswerMatches(answer1, 81, resultCaptor.getValue());
assertEquals(0, fakeClock.numPendingTasks());
fakeTicker.advance(1, TimeUnit.DAYS);
resolver.refresh();
assertEquals(1, fakeExecutor.runDueTasks());
verifyNoMoreInteractions(mockListener);
assertAnswerMatches(answer1, 81, resultCaptor.getValue());
assertEquals(0, fakeClock.numPendingTasks());
resolver.shutdown();
verify(mockResolver).resolveAddress(Matchers.anyString());
}
@Test
public void resolve_usingCache() throws Exception {
long ttl = 60;
System.setProperty(DnsNameResolver.NETWORKADDRESS_CACHE_TTL_PROPERTY, Long.toString(ttl));
final List<InetAddress> answer = createAddressList(2);
String name = "foo.googleapis.com";
FakeTicker fakeTicker = new FakeTicker();
DnsNameResolver resolver =
newResolver(name, 81, GrpcUtil.NOOP_PROXY_DETECTOR, Stopwatch.createUnstarted(fakeTicker));
AddressResolver mockResolver = mock(AddressResolver.class);
when(mockResolver.resolveAddress(Matchers.anyString()))
.thenReturn(answer)
.thenThrow(new AssertionError("should not reach here."));
resolver.setAddressResolver(mockResolver);
resolver.start(mockListener);
assertEquals(1, fakeExecutor.runDueTasks());
verify(mockListener).onAddresses(resultCaptor.capture(), any(Attributes.class));
assertAnswerMatches(answer, 81, resultCaptor.getValue());
assertEquals(0, fakeClock.numPendingTasks());
// this refresh should return cached result
fakeTicker.advance(ttl - 1, TimeUnit.SECONDS);
resolver.refresh();
assertEquals(1, fakeExecutor.runDueTasks());
verifyNoMoreInteractions(mockListener);
assertAnswerMatches(answer, 81, resultCaptor.getValue());
assertEquals(0, fakeClock.numPendingTasks());
resolver.shutdown();
verify(mockResolver).resolveAddress(Matchers.anyString());
}
@Test
public void resolve_cacheExpired() throws Exception {
long ttl = 60;
System.setProperty(DnsNameResolver.NETWORKADDRESS_CACHE_TTL_PROPERTY, Long.toString(ttl));
final List<InetAddress> answer1 = createAddressList(2);
final List<InetAddress> answer2 = createAddressList(1);
String name = "foo.googleapis.com";
FakeTicker fakeTicker = new FakeTicker();
DnsNameResolver resolver =
newResolver(name, 81, GrpcUtil.NOOP_PROXY_DETECTOR, Stopwatch.createUnstarted(fakeTicker));
AddressResolver mockResolver = mock(AddressResolver.class);
when(mockResolver.resolveAddress(Matchers.anyString())).thenReturn(answer1).thenReturn(answer2);
resolver.setAddressResolver(mockResolver);
resolver.start(mockListener);
assertEquals(1, fakeExecutor.runDueTasks());
verify(mockListener).onAddresses(resultCaptor.capture(), any(Attributes.class));
assertAnswerMatches(answer1, 81, resultCaptor.getValue());
assertEquals(0, fakeClock.numPendingTasks());
fakeTicker.advance(ttl + 1, TimeUnit.SECONDS);
resolver.refresh();
assertEquals(1, fakeExecutor.runDueTasks());
verify(mockListener, times(2)).onAddresses(resultCaptor.capture(), any(Attributes.class));
assertAnswerMatches(answer2, 81, resultCaptor.getValue());
assertEquals(0, fakeClock.numPendingTasks());
resolver.shutdown();
verify(mockResolver, times(2)).resolveAddress(Matchers.anyString());
}
@Test
public void resolve_invalidTtlPropertyValue() throws Exception {
System.setProperty(DnsNameResolver.NETWORKADDRESS_CACHE_TTL_PROPERTY, "not_a_number");
resolveDefaultValue();
}
@Test
public void resolve_noPropertyValue() throws Exception {
System.clearProperty(DnsNameResolver.NETWORKADDRESS_CACHE_TTL_PROPERTY);
resolveDefaultValue();
}
private void resolveDefaultValue() throws Exception {
final List<InetAddress> answer1 = createAddressList(2);
final List<InetAddress> answer2 = createAddressList(1);
String name = "foo.googleapis.com";
FakeTicker fakeTicker = new FakeTicker();
DnsNameResolver resolver =
newResolver(name, 81, GrpcUtil.NOOP_PROXY_DETECTOR, Stopwatch.createUnstarted(fakeTicker));
AddressResolver mockResolver = mock(AddressResolver.class);
when(mockResolver.resolveAddress(Matchers.anyString())).thenReturn(answer1).thenReturn(answer2);
resolver.setAddressResolver(mockResolver);
resolver.start(mockListener);
assertEquals(1, fakeExecutor.runDueTasks());
verify(mockListener).onAddresses(resultCaptor.capture(), any(Attributes.class));
assertAnswerMatches(answer1, 81, resultCaptor.getValue());
assertEquals(0, fakeClock.numPendingTasks());
fakeTicker.advance(DnsNameResolver.DEFAULT_NETWORK_CACHE_TTL_SECONDS, TimeUnit.SECONDS);
resolver.refresh();
assertEquals(1, fakeExecutor.runDueTasks());
verifyNoMoreInteractions(mockListener);
assertAnswerMatches(answer1, 81, resultCaptor.getValue());
assertEquals(0, fakeClock.numPendingTasks());
fakeTicker.advance(1, TimeUnit.SECONDS);
resolver.refresh();
assertEquals(1, fakeExecutor.runDueTasks());
verify(mockListener, times(2)).onAddresses(resultCaptor.capture(), any(Attributes.class));
assertAnswerMatches(answer2, 81, resultCaptor.getValue());
assertEquals(0, fakeClock.numPendingTasks());
resolver.shutdown();
verify(mockResolver, times(2)).resolveAddress(Matchers.anyString());
}
@Test @Test
public void resolveAll_nullResourceResolver() throws Exception { public void resolveAll_nullResourceResolver() throws Exception {
final String hostname = "addr.fake"; final String hostname = "addr.fake";
@ -502,8 +329,7 @@ public class DnsNameResolverTest {
"password"); "password");
when(alwaysDetectProxy.proxyFor(any(SocketAddress.class))) when(alwaysDetectProxy.proxyFor(any(SocketAddress.class)))
.thenReturn(proxyParameters); .thenReturn(proxyParameters);
DnsNameResolver resolver = DnsNameResolver resolver = newResolver(name, port, alwaysDetectProxy);
newResolver(name, port, alwaysDetectProxy, Stopwatch.createUnstarted());
AddressResolver mockAddressResolver = mock(AddressResolver.class); AddressResolver mockAddressResolver = mock(AddressResolver.class);
when(mockAddressResolver.resolveAddress(Matchers.anyString())).thenThrow(new AssertionError()); when(mockAddressResolver.resolveAddress(Matchers.anyString())).thenThrow(new AssertionError());
resolver.setAddressResolver(mockAddressResolver); resolver.setAddressResolver(mockAddressResolver);