From cb0d23923f7cc05cf67942d80aa73cbe11533652 Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Fri, 16 Nov 2018 10:37:29 +0100 Subject: [PATCH] Refresh DNS configuration each 5 minutes. (#8468) Motivation: We should refresh the DNS configuration each 5 minutes to be able to detect changes done by the user. This is inline with what OpenJDK is doing Modifications: Refresh config every 5 minutes. Result: Be able to consume changes made by the user. --- .../dns/DnsServerAddressStreamProviders.java | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/resolver-dns/src/main/java/io/netty/resolver/dns/DnsServerAddressStreamProviders.java b/resolver-dns/src/main/java/io/netty/resolver/dns/DnsServerAddressStreamProviders.java index 7765b95387..fbcd8cc9c1 100644 --- a/resolver-dns/src/main/java/io/netty/resolver/dns/DnsServerAddressStreamProviders.java +++ b/resolver-dns/src/main/java/io/netty/resolver/dns/DnsServerAddressStreamProviders.java @@ -18,18 +18,45 @@ package io.netty.resolver.dns; import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.UnstableApi; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; + /** * Utility methods related to {@link DnsServerAddressStreamProvider}. */ @UnstableApi public final class DnsServerAddressStreamProviders { + // We use 5 minutes which is the same as what OpenJDK is using in sun.net.dns.ResolverConfigurationImpl. + private static final long REFRESH_INTERVAL = TimeUnit.MINUTES.toNanos(5); + // TODO(scott): how is this done on Windows? This may require a JNI call to GetNetworkParams // https://msdn.microsoft.com/en-us/library/aa365968(VS.85).aspx. private static final DnsServerAddressStreamProvider DEFAULT_DNS_SERVER_ADDRESS_STREAM_PROVIDER = + new DnsServerAddressStreamProvider() { + private volatile DnsServerAddressStreamProvider currentProvider = provider(); + private final AtomicLong lastRefresh = new AtomicLong(System.nanoTime()); + + @Override + public DnsServerAddressStream nameServerAddressStream(String hostname) { + long last = lastRefresh.get(); + DnsServerAddressStreamProvider current = currentProvider; + if (System.nanoTime() - last > REFRESH_INTERVAL) { + // This is slightly racy which means it will be possible still use the old configuration for a small + // amount of time, but that's ok. + if (lastRefresh.compareAndSet(last, System.nanoTime())) { + current = currentProvider = provider(); + } + } + return current.nameServerAddressStream(hostname); + } + + private DnsServerAddressStreamProvider provider() { // If on windows just use the DefaultDnsServerAddressStreamProvider.INSTANCE as otherwise // we will log some error which may be confusing. - PlatformDependent.isWindows() ? DefaultDnsServerAddressStreamProvider.INSTANCE : + return PlatformDependent.isWindows() ? DefaultDnsServerAddressStreamProvider.INSTANCE : UnixResolverDnsServerAddressStreamProvider.parseSilently(); + } + }; private DnsServerAddressStreamProviders() { }