Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Httpurlconnection DNS resolution with multiple IP addresses

I'm using Java's HttpUrlConnection to hit foo.com

foo.com has multiple A-Records that point to different IP addresses (1.1.1.1 and 1.1.1.2)

If my first connect call resolves to 1.1.1.1, but then that machine goes down, will a subsequent connect call recognize this and try to connect on 1.1.1.2 instead?

Or do I need to implement this sort of logic myself using the INetAddress api?

like image 560
Adam Avatar asked Sep 19 '11 23:09

Adam


1 Answers

I was able to resolve this by using Apache Commons HttpClient, see the code snippet below.

Like I feared, the URLConnection provided by java.net is a very simplistic implementation and will only try the first IP address from the resolved list. If you really are not allowed to use another library, you will have to write your own error handling. It's kinda messy, since you will need to resolve all IPs before hand using InetAddress, and connect to each IP passing the "Host: domain.name" header to the HTTP stack yourself until one of the IPs responds.

The Apache library is greatly more robust and allows for a great deal of customization. You can control how many times it will retry and, most importantly, it will automatically try all IP addresses resolved to the same name until one of them responds successfully.

HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() {
    @Override
    public boolean retryRequest(IOException exception, int count, HttpContext context) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
        }
        return count < 30;
    }
};

ConnectionKeepAliveStrategy keepAlive = new ConnectionKeepAliveStrategy() {
    @Override
    public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
        return 500;
    }
};

DefaultHttpClient httpclient = new DefaultHttpClient();
httpclient.getParams().setParameter("http.socket.timeout", new Integer(2000));
httpclient.getParams().setParameter("http.connection.timeout", new Integer(2000));
httpclient.setHttpRequestRetryHandler(myRetryHandler);
httpclient.setKeepAliveStrategy(keepAlive);
HttpGet httpget = new HttpGet("http://remotehost.com");
HttpResponse httpres = httpclient.execute(httpget);
InputStream is = httpres.getEntity().getContent();

I hope this helps!

like image 66
JulioHM Avatar answered Nov 10 '22 00:11

JulioHM