HttpClient 4 hangs silently on socketRead

I have an application that continuously probes a remote HTTP API using a keep-alive connection.

Rarely, but sometimes the application will run silently after work for a while.
The socket is still open, but the remote API is not returning any data.

Httpclient has socket timeouts and connection timeouts, but how do I handle the timeout where we are already connected, the socket is still open, but the server is not returning data?

netstat -np

for the process:

Proto Recv-Q Send-Q Local Address               Foreign Address             State       PID/Program name
tcp        0      0 redactedlocalip:31136       redactedforeignip:80        ESTABLISHED 11145/java   

      

My httpclient:

SocketConfig socketConfig = SocketConfig.copy(SocketConfig.DEFAULT).setSoTimeout(25000).build();
BasicHttpClientConnectionManager connectionManager = new BasicHttpClientConnectionManager();
connectionManager.setSocketConfig(socketConfig);
return HttpClients
        .custom()
        .setUserAgent(USER_AGENT)
        .setConnectionManager(connectionManager)
        .setRetryHandler(new DefaultHttpRequestRetryHandler())
        .build();

      

Resetting the main thread:

"main" #11 prio=5 os_prio=0 tid=0x00007f6b802ce800 nid=0x2b9f runnable [0x00007f6b675ec000]
   java.lang.Thread.State: RUNNABLE
        at java.net.SocketInputStream.socketRead0(Native Method)
        at java.net.SocketInputStream.read(SocketInputStream.java:150)
        at java.net.SocketInputStream.read(SocketInputStream.java:121)
        at org.apache.http.impl.io.SessionInputBufferImpl.streamRead(SessionInputBufferImpl.java:139)
        at org.apache.http.impl.io.SessionInputBufferImpl.fillBuffer(SessionInputBufferImpl.java:155)
        at org.apache.http.impl.io.SessionInputBufferImpl.readLine(SessionInputBufferImpl.java:284)
        at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:140)
        at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:57)
        at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:261)
        at org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseHeader(DefaultBHttpClientConnection.java:165)
        at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:272)
        at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:124)
        at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:271)
        at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
        at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)
        at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
        at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)
        at redacted.app.code.executemyRequest(MyClass.java:117)

      

I am using the latest version from maven "org.apache.httpcomponents: httpclient: 4.5"

+3


source to share


1 answer


The problem was a poorly managed HTTP server that never responded to certain requests but continued to maintain a TCP connection and send / receive keep-alive packets.
Apache HTTPClient does not have a built-in timeout to resolve these scenarios, the solution is to manually call the HTTPRequest $ abort () method after the designated amount of timeout.
Of course, it needs to be called from another thread, since the calling thread will be blocked.



+2


source







All Articles