hc-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Oleg Kalnichevski (JIRA)" <j...@apache.org>
Subject [jira] [Resolved] (HTTPCLIENT-1263) CachingHttpClient not consuming backend HttpResponse entity causing PoolingClientConnectionManager to become unresponsive
Date Fri, 23 Nov 2012 13:00:58 GMT

     [ https://issues.apache.org/jira/browse/HTTPCLIENT-1263?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]

Oleg Kalnichevski resolved HTTPCLIENT-1263.
-------------------------------------------

       Resolution: Fixed
    Fix Version/s: 4.2.3

Francois-Xavier, 
Many thanks for contributing the patch. I committed it to both trunk and 4.2.x with some additional
safeguards for those cases when response processing is terminated with an exception.

Curiously enough, the problem was partially caused by ZIPInputStream never reading past ZIP
content structure thus never triggering an end of stream condition (read operation returning
-1), which is used by HttpClient to automatically release the underlying HTTP connection back
to the pool.

Oleg
                
> CachingHttpClient not consuming backend HttpResponse entity causing PoolingClientConnectionManager
to become unresponsive
> -------------------------------------------------------------------------------------------------------------------------
>
>                 Key: HTTPCLIENT-1263
>                 URL: https://issues.apache.org/jira/browse/HTTPCLIENT-1263
>             Project: HttpComponents HttpClient
>          Issue Type: Bug
>          Components: HttpClient
>    Affects Versions: 4.2.1
>            Reporter: Bryant Harris
>              Labels: cache, connection-pooling, consumed
>             Fix For: 4.2.3
>
>         Attachments: HTTPCLIENT-1263.txt
>
>
> I've noticed that when issuing requests via a pooled and cached HttpClient that the client
eventually becomes unresponsive (which appears to be because an HttpEntity is not getting
consumed properly).
> Steps to reproduce.
> 1. Here is how I've configured all the relevant classes.
>     HttpClient standardClient = null;
>     HttpClient cachedClient = null;
>     PoolingClientConnectionManager connectionManager = null;
>     protected synchronized HttpClient getStandardClient() {
>       if ( standardClient == null ) {
>         connectionManager = new PoolingClientConnectionManager();
>         connectionManager.setMaxTotal(2);
>         connectionManager.closeIdleConnections(120, TimeUnit.SECONDS);
>         standardClient = new DecompressingHttpClient( new DefaultHttpClient (connectionManager));
>       }
>       return standardClient;
>     }
> protected synchronized HttpClient getCachedClient() {
>   if ( cachedClient == null ) {
>     CacheConfig cacheConfig = new CacheConfig();
>     cacheConfig.setMaxObjectSize( 512*1024 );
>     cacheConfig.setMaxCacheEntries( 10 );
>     cachedClient = new CachingHttpClient(getStandardClient(),
>                                          getCacheStorage(),
>                                          cacheConfig);
>   }
>   return cachedClient;
> }
> As you can see I have two http clients. A caching http client that wraps the standard
client.
> Now what I've found is that if I remove cachedClient and only use standardClient, I don't
have any issues with the pool hanging and orphaned connections.
> 2.  Here is my code for how I issue and consume requests
>     HttpClient httpClient = cacheOkay ? getCachedClient() : getStandardClient();  
>     HttpResponse response = httpClient.execute(request, localContext);
>     HttpEntity resEntity = response.getEntity();  
>     int responseStatus = response.getStatusLine().getStatusCode();
>     byte[] responseBody = EntityUtils.toByteArray(resEntity);
>     EntityUtils.consume(resEntity);
> If you set up a test like this and use the cached client, it will hang fairly quickly.
> I've been able to work around this by creating the CachingHttpClient as follows:
>     protected synchronized HttpClient getCachedClient() {
>     	if ( cachedClient == null ) {
>     		WhosHereApplication application = WhosHereApplication.getInstance();
>     		cachedClient = new CachingHttpClient(getStandardClient(),
>     											 new HeapResourceFactory() {
> 													@Override
> 													public Resource generate(
> 															String requestId,
> 															InputStream instream,
> 															InputLimit limit)
> 															throws IOException {
> 														try {
> 															return super.generate(requestId, instream, limit);
> 														}
> 														finally {
> 															instream.close();
> 														}
> 													}
>     			
>     											 },
>     				                             application.getCacheStorage(),
>     				                             application.getCacheConfig());
>     		Log.i(tag, "Creating CachingHttpClient");
>     	}
>     		
>     	return cachedClient;
>     }
> Notice the inline subclass of HeapResourceFactory where I add the stream close call.
 Once I add this the caching client no longer freezes up.
> I'm not familiar enough with the source code to pinpoint the issue, but appears the back
end entity is not getting consumed properly, forcing this work around.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

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


Mime
View raw message