On Wed, 2015-05-13 at 20:58 +0000, Mark A. Claassen wrote:
> The 4.4.1 code doesn't seem to help.
> 
> I have been able to reproduce the issue more regularly now.  It seems to have 
> to do with keep-alives and if the client takes longer to read the message 
> than the keep alive value.
> 

Hi Mark

Then, it is all very simple. There are several ways to make HttpClient
either discard potentially half-closed connections, test them for
'staleness' or automatically recover from NoHttpResponseException.


> In my test case I open the connection, read all the data, sleep for a while, 
> then close the connection.
> If my sleep is a bit longer than the keep-alive value, I will get a 
> org.apache.http.NoHttpResponseException.  If my sleep value is larger, I will 
> get a java.net.SocketException.
> (Keep-Alive is 5000 millis.  If I sleep for 6000, I will get a 
> NoHttpResponseException.  If I sleep for 11000, I will get a SocketException.
> 

The default maximum inactivity period used by the pooling connection
manager is exactly 5000 ms. Please try reducing this value to, say, 2000
ms

---
PoolingHttpClientConnectionManager cm = new
PoolingHttpClientConnectionManager();
cm.setValidateAfterInactivity(2000);

CloseableHttpClient client = HttpClients.custom()
        .setConnectionManager(cm)
        .build();
--- 

This should make the problem go away.

> If I use the NoConnectionReuseStrategy, the problem goes away.
> 
> Is something set up for my keep alives?  I put some breakpoints in 
> CPool.java.  I can see connections being created, but the validate() method 
> of CPool is never getting called.
> 
> I am curious this part of AbstractConnPool.java.  This seems like if the 
> server invalidated a connection early, the validate check would never happen.
> 
>                     } else if (this.validateAfterInactivity > 0) {
>                         if (entry.getUpdated() + this.validateAfterInactivity 
> <= System.currentTimeMillis()) {
>                             if (!validate(entry)) {
>                                 entry.close();
>                             }
>                         }
>                     }
> Scenario:
>       Server sends data.
>       Client reads packet, processes it for 6 seconds
>       Server senses that inactivity for 5 seconds, closes connection
>       Client closes connection and places entry back in the pool
>       Connection immediately leased to another thread
>       Time between release and close is almost nothing
>       Pool releases stale connection.
> 

You can force TTL (total time to live) for connections to avoid this
problem

---
PoolingHttpClientConnectionManager cm = new
PoolingHttpClientConnectionManager(3000, TimeUnit.MILLISECONDS);
cm.setValidateAfterInactivity(1000);

CloseableHttpClient client = HttpClients.custom()
        .setConnectionManager(cm)
        .build();
---

Hope this helps

Oleg


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to