Dear All,
Working on making Java-monitor more robust against DNS outage issues gave me some insight into Java's DNS caching behaviour. The default caching behaviour may seem nice at first, but is has some serious ramifications for long-running processes, such as the ones we are dealing with.
Regardless of whether you use Java-monitor, you may want to take a few minutes to consider the DNS cache behaviour that your application is using.
Java 1.6 introduced a change to the default DNS caching behaviour. The default value for networkaddress.cache.ttl changed from -1 (cache forever) to a system-dependent value, but only if you have no security manager installed. The idea was for this to work as a robustness against DNS cache poisoning.
Default DNS cache behaviour for Java 1.4 and Java 1.5, taken from the API documentation of
java.net.InetAddress.
networkaddress.cache.ttl (default: -1)
Indicates the caching policy for successful name lookups from the name service. The value is specified as as integer to indicate the number of seconds to cache the successful lookup. A value of -1 indicates "cache forever".
networkaddress.cache.negative.ttl (default: 10)
Indicates the caching policy for un-successful name lookups from the name service. The value is specified as as integer to indicate the number of seconds to cache the failure for un-successful lookups. A value of 0 indicates "never cache". A value of -1 indicates "cache forever".
Default DNS cache behaviour for Java 1.6, taken from the API documentation of
java.net.InetAddress.
networkaddress.cache.ttl
Specified in java.security to indicate the caching policy for successful name lookups from the name service.. The value is specified as as integer to indicate the number of seconds to cache the successful lookup. A value of -1 indicates "cache forever". The default behavior is to cache forever when a security manager is installed, and to cache for an implementation specific period of time, when a security manager is not installed.
networkaddress.cache.negative.ttl (default: 10)
Indicates the caching policy for un-successful name lookups from the name service. The value is specified as as integer to indicate the number of seconds to cache the failure for un-successful lookups. A value of 0 indicates "never cache". A value of -1 indicates "cache forever".
The most important change is that the default behaviour for networkaddress.cache.ttl. That is now set to 30 seconds.
Personally, I don't understand why one would cache for just a few seconds. That means that you almost never take anything from the cache. I am also disappointed to learn that I cannot plug in my own cache implementation programatically. That would allow me to easily fall back to previously cached and even expired DNS entries in case a DNS server dies.
To read more on Java's DNS cache policy, have a look at
this discussion about LimeWire's problems with Java's DNS cache. Granted, LimeWire is an extreme case, because it deals with massive number of peer hosts. It still shows how a quick cache thrown into the code may grow out of proportion if you are not careful.
I used the following code to print out that the default of networkaddress.cache.ttl is 30 seconds for for my JDK 1.6. This is Sun-specific code. It's just to get a peek at the internals, so that's ok. JUst don't use it in your production environment. :-)
Code:
public class Foo {
public static void main(String[] args) {
System.out.println(sun.net.InetAddressCachePolicy.get());
}
}
Please notice that changing the values for these settings is not straightforward. They are security properties, not regular system properties. You can find how to set them in
this discussion, at the bottom of the page.
I am looking forward to hear from you what values you guys use for networkaddress.cache.ttl and networkaddress.cache.negative.ttl.
Kees Jan