Jan Vladimir Mostert Jan Vladimir Mostert - 2 months ago 13
Java Question

Provide custom implementation for DNS lookup in java.net.URL class

I was wondering if it's possible to provide a custom implementation for DNS lookups on java.net.URL - my hosting provider's DNS gets flaky at certain times of day and then DNS lookups fail for a few minutes, but if I manually configure the relevant domains in my hosts file, they work fine, so what I want to do is have some sort of DNS cache at a software level, if DNS lookup succeed, update the cache, if it fails, fall back to the cached IP address and open the URLConnection on that IP address.

This is my URL connection implementation:

URL endpoint = new URL(null, url, new URLStreamHandler() {
@Override
protected URLConnection openConnection(URL url)
throws IOException {
URL target = new URL(url.toString());
URLConnection connection = target.openConnection();
// Connection settings
connection.setConnectTimeout(connectionTimeout);
connection.setReadTimeout(readTimeout);
return (connection);
}
});


I was looking at proxies on Oracle, but can't see any immediate way to do custom DNS lookups at the software level.

Limitations:

1: It needs to work in Java6 (maybe Java7, but the client won't be switching to Java8 anytime soon)

2: Can't add JVM args

3: I don't own these endpoints, so substituting the hostname with an IP address is not a solution since load balancers will serve different content / APIs depending on whether you come from a hostname or an IP address. As an example: mail.google.com resolves to 216.58.223.37, going to that IP address will serve google.com content and not mail.google.com content, since both services are sitting behind the same load balancer using a single IP address.

4: I don't know how many URLs' DNS resolutions I'll need to cache, but I do know it won't be more than a 1000. Ideal solution would be to have the DNS resolutions in a static hashmap, if any DNS resolution succeed, update the hashmap, if it fails, use the DNS resolution in the hashmap.

5: If there's a native java solution, I'd prefer that over using JNI - Understanding host name resolution and DNS behavior in Java

Answer

Giving Java direct access to add / remove entries in the /etc/hosts file was the best I could come up with. One services sitting on another vm will resolve hosts and get their IP addresses and validate that it can access those domains using the resolved IP address. If it can't access it (due to flaky DNS servers resolving to the wrong IP addresses, it will simply ignore those domains until it can resolve properly)

If successful, send a message back to the other vm where the application is running that will update the /etc/hosts file.

Not a pure Java solution (we're making use of the hosts file to resolve domains properly), but it gets the job done.

Comments