hc-httpclient-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Oleg Kalnichevski <ol...@apache.org>
Subject Re: How to close persistent non-idle connections after some time
Date Wed, 18 Sep 2013 13:54:05 GMT
On Wed, 2013-09-18 at 15:24 +0200, Boris Granveaud wrote:
> Le 18/09/2013 13:23, Oleg Kalnichevski a écrit :
> > On Wed, 2013-09-18 at 11:39 +0200, Boris Granveaud wrote:
> >> Hi,
> >>
> >> I would like to automatically close persistent connections after some
> >> time, *even if they are used* (but only at the end of a query of course).
> >>
> >> I need this so that when I would like to deploy a new middle server, I
> >> can remove it from the production pool of servers and wait for example
> >> 60 seconds that the front webapps close their persistent HttpClient
> >> connections.
> >>
> >> I have seen that you can set a timeToLive parameter in
> >> PoolingHttpClientConnectionManager but this is used only to close idle
> >> connections.
> >>
> >> I cannot use ConnectionReuseStrategy and KeepAliveStrategy because I
> >> don't have access to the connection that is used.
> >>
> >> Finally, I tried to extend PoolingHttpClientConnectionManager to remove
> >> the call to updateExpiry in releaseConnection:
> >>
> >>       public void releaseConnection(
> >>               final HttpClientConnection managedConn,
> >>               final Object state,
> >>               final long keepalive, final TimeUnit tunit) {
> >> ...
> >>                   if (conn.isOpen()) {
> >>                       entry.setState(state);
> >>                       entry.updateExpiry(keepalive, tunit != null ? tunit
> >> : TimeUnit.MILLISECONDS);
> >>
> >> but this is not feasible as CPoolEntry and CPoolProxy which are used in
> >> this method are not public classes.
> >>
> >> Any idea?
> >>
> >> Thanks,
> >> Boris.
> >>
> > AbstractConnPool class, which CPool is based upon, provides #enumLeased
> > method that can be used to enumerate leased connections and optionally
> > close some or all of them. Truth to be told, I simply forgot to add a
> > corresponding method to PoolingHttpClientConnectionManager.
> >
> > Please raise a change request in JIRA for this issue. For the time being
> > you will have to resort to reflection in order to get hold of the 'pool'
> > instance variable and cast it to AbstractConnPool.
> I'm trying to implement your solution with a timer which periodically 
> enumerates leased connections and closes those which are too old, but 
> from time to time I have an exception like this:
> 
> Caused by: java.io.InterruptedIOException: Connection already shutdown
>      at 
> org.apache.http.impl.conn.DefaultManagedHttpClientConnection.bind(DefaultManagedHttpClientConnection.java:116)

> ~[httpclient-4.3.jar:4.3]
>      at 
> org.apache.http.impl.conn.HttpClientConnectionOperator.connect(HttpClientConnectionOperator.java:110)

> ~[httpclient-4.3.jar:4.3]
>      at 
> org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:314)

> ~[httpclient-4.3.jar:4.3]
>      at 
> org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:357)

> ~[httpclient-4.3.jar:4.3]
>      at 
> org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:218) 
> ~[httpclient-4.3.jar:4.3]
>      at 
> org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:194) 
> ~[httpclient-4.3.jar:4.3]
>      at 
> org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:186)

> ~[httpclient-4.3.jar:4.3]
>      at 
> org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)

> ~[httpclient-4.3.jar:4.3]
>      at 
> org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)

> ~[httpclient-4.3.jar:4.3]
> 
> I suppose this is due to the fact that the connection is closed in 
> another thread. I do call CPoolEntry.shutdownConnection() instead of 
> CPoolEntry.closeConnection() but there must be a race condition somewhere.
> 

You are basically shutting down the connection which is currently being
used to execute a request. This can cause all sorts of exceptions
depending on what stage execution process is at. InterruptedIOException
is perfectly legit in this context.

> I'm not very comfortable with this solution because of these thread 
> synchronization issues. I also have to do the same on idle connections 
> and each enumeration, even if it is fast, locks the pool. It is a pity 
> that it is not possible to alter the behavior of 
> PoolingHttpClientConnectionManager.releaseConnection.
> 
> Here is my complete code if you see what's wrong:
> 

There is probably nothing wrong with your code. If you intend to shut
down connections 'midair' so to speak, this is what you have to live
with. Changing #releaseConnection will not help given that time to live
and expiry attributes apply to idle connections only.

Oleg



---------------------------------------------------------------------
To unsubscribe, e-mail: httpclient-users-unsubscribe@hc.apache.org
For additional commands, e-mail: httpclient-users-help@hc.apache.org


Mime
View raw message