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)......




Это просто простое однопоточное приложение. Как я могу освободить это соединение?

510   12  

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

    Ничего не найдено.