You are viewing a plain text version of this content. The canonical link for it is here.
Posted to httpclient-users@hc.apache.org by Todd W Lainhart <la...@us.ibm.com> on 2014/09/15 17:08:43 UTC

PoolingHttpClientConnectionManager and CloseableHttpResponse

I'm seeing some IllegalStateExceptions (ISE) thrown from HC4 (4.3.5) in my 
code, and suspect that I'm misusing the library.  It happens sporadically, 
probably when the JVM or the machine it's running on is under load.  I 
suspect non-thread-safe code (in my code).

Perhaps related to this, I first want to confirm that I understand the 
programming model for PoolingHttpClientConnectionManager (PHCCM) and 
CloseableHttpResponse (CHR).

CHR encapsulates both the response stream and the underlying network 
connection.  If I want to reuse the underlying connection for performance 
reasons, my only responsibility is to consume the entity content of the 
response.  If (for some reason) I don't want to reuse the underlying 
connection, I both consume the response entity and close the CHR.  This 
behavior regardless of what type of HttpClientConnectionManager I'm using 
(e.g. closing the CHR really does close it, as opposed to keep it open and 
making it available in PHCCM).  HttpClientUtils and EntityUtils provide 
convenience routines for these behaviors.

Do I have the programming model right?

Regarding the ISE - when thrown, typically it's thrown from 
PHCCM.requestConnection(...), when the AbstractConnPool is checking 
whether or not the pool has been previously shutdown.  So, the application 
is in a state where something has told the connection manager to shutdown, 
while there continue to be references to it.  I see two places where 
shutdown/close is called - in the close/finalizer methods of PHCCM, and in 
the close method of InternalHttpClient.  I can't see any other paths where 
PHCCM and its pools could be shutdown.  Note that I'm using my own 
Registry<ConnectionSocketFactory>, to allow for custom socket factories 
for "http" and "https".

Regarding shutting down the ConnectionManager - is this a relatively fast 
operation or can it block based on the status of its underlying 
connections?





Todd Lainhart
Rational software
IBM Corporation
550 King Street, Littleton, MA 01460-1250
1-978-899-4705
2-276-4705 (T/L)
lainhart@us.ibm.com

Re: PoolingHttpClientConnectionManager and CloseableHttpResponse

Posted by Oleg Kalnichevski <ol...@apache.org>.
On Tue, 2014-09-16 at 15:49 -0400, Todd W Lainhart wrote:
> > 
> > The connection manager has no way of knowing if a connection is still 
> > being used. No matter what it needs to be notified that the connection 
> > can be re-claimed (and either kept alive for further re-use or 
> > discarded). The #release method looks like a natural way of doing that.
> > 
> > Oleg
> > 
> 
> Thanks - I'm still trying to grok, at a lower-level, the relationship 
> between the connection, the manager, and the pool.  I've got past the 
> connection pool shutdown problem (my code).  I'm now seeing ISE raised on 
> an unexpectedly closed HttpConnection (stack trace below).  I'm not 
> getting this one, as the RequestExecutor is successfully sending the 
> request, but it's erring out on the closed connection.
> 
> Assuming that the connection is not shared across threads, and not being 
> closed by another thread, what would be a cause of the unexpected 
> connection close between the request and response?
> 

HttpUriRequest#abort method shuts down the underlying connection. Any
further interaction with the same connection is likely to result in
ConnectionShutdownException. 

> Thanks for your help.  My suspicion is that there is still someone holding 
> onto a connection, while in parallel, the connection manager from which 
> that connection was provisioned is shutdown. I'm wondering if there might 
> be another scenario.
> 

This can happen if the request is aborted while still being executed.
However, the #abort method usually needs to be called from another
thread.

Oleg 

> 
> 
> Caused by: java.lang.IllegalStateException: Connection is not open
>         at org.apache.http.util.Asserts.check(Asserts.java:34)
>         at 
> org.apache.http.impl.BHttpConnectionBase.ensureOpen(BHttpConnectionBase.java:128)
>         at 
> org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseEntity(DefaultBHttpClientConnection.java:172)
>         at 
> org.apache.http.impl.conn.CPoolProxy.receiveResponseEntity(CPoolProxy.java:157)
>         at 
> org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:273)
>         at 
> org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:123)
>         at 
> org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:254)
>         at 
> org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:195)
>         at 
> org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:86)
>         at 
> org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108)
>         at 
> org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)



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


Re: PoolingHttpClientConnectionManager and CloseableHttpResponse

Posted by Todd W Lainhart <la...@us.ibm.com>.
> 
> The connection manager has no way of knowing if a connection is still 
> being used. No matter what it needs to be notified that the connection 
> can be re-claimed (and either kept alive for further re-use or 
> discarded). The #release method looks like a natural way of doing that.
> 
> Oleg
> 

Thanks - I'm still trying to grok, at a lower-level, the relationship 
between the connection, the manager, and the pool.  I've got past the 
connection pool shutdown problem (my code).  I'm now seeing ISE raised on 
an unexpectedly closed HttpConnection (stack trace below).  I'm not 
getting this one, as the RequestExecutor is successfully sending the 
request, but it's erring out on the closed connection.

Assuming that the connection is not shared across threads, and not being 
closed by another thread, what would be a cause of the unexpected 
connection close between the request and response?

Thanks for your help.  My suspicion is that there is still someone holding 
onto a connection, while in parallel, the connection manager from which 
that connection was provisioned is shutdown. I'm wondering if there might 
be another scenario.



Caused by: java.lang.IllegalStateException: Connection is not open
        at org.apache.http.util.Asserts.check(Asserts.java:34)
        at 
org.apache.http.impl.BHttpConnectionBase.ensureOpen(BHttpConnectionBase.java:128)
        at 
org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseEntity(DefaultBHttpClientConnection.java:172)
        at 
org.apache.http.impl.conn.CPoolProxy.receiveResponseEntity(CPoolProxy.java:157)
        at 
org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:273)
        at 
org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:123)
        at 
org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:254)
        at 
org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:195)
        at 
org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:86)
        at 
org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108)
        at 
org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)

Re: PoolingHttpClientConnectionManager and CloseableHttpResponse

Posted by Oleg Kalnichevski <ol...@apache.org>.
On 16/09/14 16:23 , Todd W Lainhart wrote:
>>
>> You can just close the response. If response content has not been fully
>> consumed CloseableHttpResponse#close will NOT attempt to salvage the
>> underlying connection and will simply shut it down and release it back
>> to the pool in a non-reusable state.
>>
>> Think of CloseableHttpResponse#close as a safe-guard for 'unhappy'
>> execution flows.
>>
>
> Thanks.  I did see close getting called during execution retries, and
> wondered why that was a "special" case.  Out of curiosity, why return the
> connection to the pool in a non-reusable state, as opposed to just
> dropping it from the pool?
>

The connection manager has no way of knowing if a connection is still 
being used. No matter what it needs to be notified that the connection 
can be re-claimed (and either kept alive for further re-use or 
discarded). The #release method looks like a natural way of doing that.

Oleg

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


Re: PoolingHttpClientConnectionManager and CloseableHttpResponse

Posted by Todd W Lainhart <la...@us.ibm.com>.
> 
> You can just close the response. If response content has not been fully
> consumed CloseableHttpResponse#close will NOT attempt to salvage the
> underlying connection and will simply shut it down and release it back
> to the pool in a non-reusable state.
> 
> Think of CloseableHttpResponse#close as a safe-guard for 'unhappy'
> execution flows.
> 

Thanks.  I did see close getting called during execution retries, and 
wondered why that was a "special" case.  Out of curiosity, why return the 
connection to the pool in a non-reusable state, as opposed to just 
dropping it from the pool?

> 
> Connection pools cannot end up in a shutdown state by itself. They must
> be explicitly shut down. There has to be something in your code that
> shuts the pool down.
> 

Yeah, clearly.  I'm still hunting that down.

> No, it is not. By default the connection manager attempts to close
> connections out gracefully, which especially in case of SSL connections
> can be a lengthy operation.
> 

I was closing the connections in a background thread, but it appears in 
some cases that a long-running close in that thread can hang the process. 
I'm investigating alternatives.

Thanks for the great response.

  -- Todd

Re: PoolingHttpClientConnectionManager and CloseableHttpResponse

Posted by Oleg Kalnichevski <ol...@apache.org>.
On Mon, 2014-09-15 at 11:08 -0400, Todd W Lainhart wrote:
> I'm seeing some IllegalStateExceptions (ISE) thrown from HC4 (4.3.5) in my 
> code, and suspect that I'm misusing the library.  It happens sporadically, 
> probably when the JVM or the machine it's running on is under load.  I 
> suspect non-thread-safe code (in my code).
> 
> Perhaps related to this, I first want to confirm that I understand the 
> programming model for PoolingHttpClientConnectionManager (PHCCM) and 
> CloseableHttpResponse (CHR).
> 
> CHR encapsulates both the response stream and the underlying network 
> connection. 

Correct.

>  If I want to reuse the underlying connection for performance 
> reasons, my only responsibility is to consume the entity content of the 
> response. 

Correct. As soon as entity is fully consumed the underlying connection
will be released back to the pool and kept alive (unless the connection
is deemed non-persistent). In this case CloseableHttpResponse#close will
have no effect.

>  If (for some reason) I don't want to reuse the underlying 
> connection, I both consume the response entity and close the CHR.

You can just close the response. If response content has not been fully
consumed CloseableHttpResponse#close will NOT attempt to salvage the
underlying connection and will simply shut it down and release it back
to the pool in a non-reusable state.

Think of CloseableHttpResponse#close as a safe-guard for 'unhappy'
execution flows.

>   This 
> behavior regardless of what type of HttpClientConnectionManager I'm using 
> (e.g. closing the CHR really does close it, as opposed to keep it open and 
> making it available in PHCCM).  HttpClientUtils and EntityUtils provide 
> convenience routines for these behaviors.
> 
> Do I have the programming model right?
> 

Pretty much. 

> Regarding the ISE - when thrown, typically it's thrown from 
> PHCCM.requestConnection(...), when the AbstractConnPool is checking 
> whether or not the pool has been previously shutdown.  So, the application 
> is in a state where something has told the connection manager to shutdown, 
> while there continue to be references to it.  I see two places where 
> shutdown/close is called - in the close/finalizer methods of PHCCM, and in 
> the close method of InternalHttpClient.  I can't see any other paths where 
> PHCCM and its pools could be shutdown.  Note that I'm using my own 
> Registry<ConnectionSocketFactory>, to allow for custom socket factories 
> for "http" and "https".
> 

Connection pools cannot end up in a shutdown state by itself. They must
be explicitly shut down. There has to be something in your code that
shuts the pool down.

> Regarding shutting down the ConnectionManager - is this a relatively fast 
> operation or can it block based on the status of its underlying 
> connections?
> 

No, it is not. By default the connection manager attempts to close
connections out gracefully, which especially in case of SSL connections
can be a lengthy operation.

Oleg



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