Search code examples
javasocketshttptimeoutapache-httpclient-4.x

How to prevent hangs on SocketInputStream.socketRead0 in Java?


Performing millions of HTTP requests with different Java libraries gives me threads hung on:

java.net.SocketInputStream.socketRead0()

which is a native function.

I tried to set up the Apache Http Client and RequestConfig to have timeouts on (I hope) everythig that is possible but still, I have (probably infinite) hangs on socketRead0. How to get rid of them?

The hung ratio is about ~1 per 10000 requests (to 10000 different hosts) and it can last probably forever (I've confirmed thread hung as still valid after 10 hours).

JDK 1.8 on Windows 7.

My HttpClient factory:

SocketConfig socketConfig = SocketConfig.custom()
            .setSoKeepAlive(false)
            .setSoLinger(1)
            .setSoReuseAddress(true)
            .setSoTimeout(5000)
            .setTcpNoDelay(true).build();

    HttpClientBuilder builder = HttpClientBuilder.create();
    builder.disableAutomaticRetries();
    builder.disableContentCompression();
    builder.disableCookieManagement();
    builder.disableRedirectHandling();
    builder.setConnectionReuseStrategy(new NoConnectionReuseStrategy());
    builder.setDefaultSocketConfig(socketConfig);

    return HttpClientBuilder.create().build();

My RequestConfig factory:

    HttpGet request = new HttpGet(url);

    RequestConfig config = RequestConfig.custom()
            .setCircularRedirectsAllowed(false)
            .setConnectionRequestTimeout(8000)
            .setConnectTimeout(4000)
            .setMaxRedirects(1)
            .setRedirectsEnabled(true)
            .setSocketTimeout(5000)
            .setStaleConnectionCheckEnabled(true).build();
    request.setConfig(config);

    return new HttpGet(url);

OpenJDK socketRead0 source

Note: Actually I have a "trick": I can schedule .getConnectionManager().shutdown() in other Thread with a cancellation of the Future if request finished properly. But, it is deprecated and also it kills whole HttpClient, not just that single request.


Solution

  • For Apache HTTP Client (blocking) I found best solution is to getConnectionManager(). and shutdown it.

    So in high-reliability solution I just schedule shutdown in other thread and in case request does not complete I'm shutting in down from other thread