HttpClient 4.0.1-как освободить соединение?
У меня есть цикл над кучей URL-адресов, для каждого из которых я делаю следующее:
private String doQuery(String url) {
HttpGet httpGet = new HttpGet(url);
setDefaultHeaders(httpGet); // static method
HttpResponse response = httpClient.execute(httpGet); // httpClient instantiated in constructor
int rc = response.getStatusLine().getStatusCode();
if (rc != 200) {
// some stuff...
return;
}
HttpEntity entity = response.getEntity();
if (entity == null) {
// some stuff...
return;
}
// process the entity, get input stream etc
}
первый запрос в порядке, второй выдает это исключение:
исключение в потоке " main"
Ява.ленг.IllegalStateException:
Недопустимое использование
SingleClientConnManager: подключение
все равно выделили. Убедитесь в том, чтобы освободить
соединение перед выделением
другой. на
орг.апаш.http.осущ.Коннектикут.SingleClientConnManager.getConnection (SingleClientConnManager.java: 199)
на
орг.апаш.http.осущ.Коннектикут.SingleClientConnManager$1.getConnection (SingleClientConnManager.Ява:173)......
Это просто простое однопоточное приложение. Как я могу освободить это соединение?
12 ответов:
рекомендуемый способ, Httpcomponents 4.1, заключается в закрытии соединения и освобождении любых базовых ресурсов:
EntityUtils.consume(HttpEntity)здесь
HttpEntityпередано-это объект ответа.
это, кажется, работает отлично:
if( response.getEntity() != null ) { response.getEntity().consumeContent(); }//ifи не забудьте использовать сущность, даже если вы не открывали ее содержимое. Например, вы ожидаете статус HTTP_OK от ответа и не получаете его, вам все равно нужно использовать сущность !
чтобы ответить на мой собственный вопрос: чтобы освободить соединение (и любые другие ресурсы, связанные с запросом), вы должны закрыть InputStream, возвращаемый HttpEntity:
InputStream is = entity.getContent(); .... process the input stream .... is.close(); // releases all resourcesС docs
начиная с версии 4.2, они ввели гораздо более удобный метод, который упрощает подключение выпуске: HttpRequestBase.releaseConnection()
Я вступаю с подробным ответом, который специально обращается к Apache HttpClient 4.0.1. Я использую эту версию HttpClient, поскольку она предоставляется WAS v8.0, и мне нужно использовать этот предоставленный HttpClient в Apache Wink v1.1.1, также предоставленный WAS v8.0, чтобы сделать некоторые вызовы REST с проверкой подлинности NTLM в Sharepoint.
чтобы процитировать Олега Кальничевского в списке рассылки Apache HttpClient:
почти весь этот код не нужен. (1) HttpClient будет автоматическое освобождение базового соединения до тех пор, пока сущность контент потребляется до конца потока; (2) HttpClient будет автоматическое освобождение базового соединения при любом исключении ввода-вывода брошенный во время чтения содержимого ответа. Никакой особенной обработки нет требуется в таком случае.
на самом деле, этого вполне достаточно, чтобы обеспечить надлежащее высвобождение ресурсов:
HttpResponse rsp = httpclient.execute(target, req); HttpEntity entity = rsp.getEntity(); if (entity != null) { InputStream instream = entity.getContent(); try { // process content } finally { instream.close(); // entity.consumeContent() would also do } }это оно.
Если ответ не будет использоваться, то запрос может быть прерван с помощью кода ниже:
// Low level resources should be released before initiating a new request HttpEntity entity = response.getEntity(); if (entity != null) { // Do not need the rest httpPost.abort(); }Ссылка: http://hc.apache.org/httpcomponents-client-ga/tutorial/html/fundamentals.html#d5e143
Apache HttpClient Version: 4.1.3
у меня есть эта проблема, когда я использую HttpClient в многопоточной среде (сервлеты). Один сервлет все еще держит соединение, а другой хочет получить соединение.
устранение:
версия 4.0 использовать
ThreadSafeClientConnManagerверсия 4.2 использовать
PoolingClientConnectionManagerи установите эти два сеттера:
setDefaultMaxPerRoute setMaxTotal
HTTP HEAD запросы должны рассматриваться несколько иначе, потому что ответ.getEntity () имеет значение null. Вместо этого необходимо захватить HttpContext, переданный в HttpClient.execute() и извлечения параметра связи, чтобы закрыть его (в HttpComponents 4.1.X в любом случае).
HttpRequest httpRqst = new HttpHead( uri ); HttpContext httpContext = httpFactory.createContext(); HttpResponse httpResp = httpClient.execute( httpRqst, httpContext ); ... // Close when finished HttpEntity entity = httpResp.getEntity(); if( null != entity ) // Handles standard 'GET' case EntityUtils.consume( entity ); else { ConnectionReleaseTrigger conn = (ConnectionReleaseTrigger) httpContext.getAttribute( ExecutionContext.HTTP_CONNECTION ); // Handles 'HEAD' where entity is not returned if( null != conn ) conn.releaseConnection(); }HttpComponents 4.2.X добавил releaseConnection () в HttpRequestBase, чтобы сделать это проще.
Если вы хотите повторно использовать соединение, то вы должны полностью использовать поток контента после каждого использования следующим образом:
EntityUtils.consume(response.getEntity())Примечание: Вы должны использовать поток содержимого, даже если код состояния не 200. Если этого не сделать, то при следующем использовании возникнет следующее:
исключение в потоке" main " java.ленг.IllegalStateException: недопустимое использование SingleClientConnManager: соединение все еще выделено. Убедитесь в том, чтобы освободить соединение перед выделением другого.
Если это одноразовое использование, то просто закрытие соединения освободит все ресурсы, связанные с ним.
У меня была такая же проблема и решил ее закрыть ответ в конце метода:
try { // make the request and get the entity } catch(final Exception e) { // handle the exception } finally { if(response != null) { response.close(); } }
Я использую HttpClient 4.5.3, используя
CloseableHttpClient#closeработал для меня.CloseableHttpResponse response = client.execute(request); try { HttpEntity entity = response.getEntity(); String body = EntityUtils.toString(entity); checkResult(body); EntityUtils.consume(entity); } finally { response.close(); }
настоятельно рекомендуем использовать обработчик для обработки ответа.
client.execute(yourRequest,defaultHanler);он автоматически освободит соединение с
consume(HTTPENTITY)метод.пример обработчика:
private ResponseHandler<String> defaultHandler = new ResponseHandler<String>() { @Override public String handleResponse(HttpResponse response) throws IOException { int status = response.getStatusLine().getStatusCode(); if (status >= 200 && status < 300) { HttpEntity entity = response.getEntity(); return entity != null ? EntityUtils.toString(entity) : null; } else { throw new ClientProtocolException("Unexpected response status: " + status); } } };
Comments