Http връзката с apache.DefaultHttpClient преминава в TIME_WAIT, без да се използва повторно

Имаме набор (GenericObjectPool) от обекти HttpClient(apache.DefaultHttpClient). Обектите HttpPost се поставят за изпълнение чрез тези клиенти, може заявката за публикация да се изпраща едновременно. Използваният протокол е: HTTP/1.1 с keepalive.

Наблюдава се по време на тестване на натоварването чрез netstat, че новите връзки към сокета се създават безразборно, а старите връзки преминават към TIME_WAIT.


Извадки от дневник: -

[Worker-2] org.apache.http.impl.conn.Wire 63 - >> "POST /INBOX/4504a09e-13c0-3853-a285-9e2b9a22f65e/1e1e5a20-a8c1-11e2-99b8-7c19e9129271 HTTP/1.1[\r][\n]"

[Worker-2] org.apache.http.impl.conn.Wire 63 - >> "Content-Type: application/json; charset=UTF-8[\r][\n]"

[Worker-2] org.apache.http.impl.conn.Wire 63 - >> "Content-Length: 117[\r][\n]"

[Worker-2] org.apache.http.impl.conn.Wire 63 - >> "Host: rwcdtgxb0402:15010[\r][\n]"

[Worker-2] org.apache.http.impl.conn.Wire 63 - >> "Connection: Keep-Alive[\r][\n]"

[Worker-2] org.apache.http.impl.conn.Wire 63 - >> "User-Agent: Apache-HttpClient/4.2.1 (java 1.5)[\r][\n]"

[Worker-2] org.apache.http.impl.conn.Wire 63 - >> "[\r][\n]"

[Worker-2] org.apache.http.impl.conn.Wire 63 - << "HTTP/1.1 200 OK[\r][\n]"

[Worker-2] org.apache.http.impl.conn.Wire 63 - << "Content-Length: 0[\r][\n]"

[Worker-2] org.apache.http.impl.conn.Wire 63 - << "[\r][\n]"

[Worker-2] org.apache.http.impl.conn.DefaultClientConnection 254 - Receiving response: HTTP/1.1 200 OK

[Worker-2] org.apache.http.impl.conn.DefaultClientConnection 257 - << HTTP/1.1 200 OK

[Worker-2] org.apache.http.impl.conn.DefaultClientConnection 260 - << Content-Length: 0

[Worker-2] org.apache.http.impl.client.DefaultRequestDirector 540 - Connection can be kept alive indefinitely

**[Worker-2] org.apache.http.impl.conn.DefaultClientConnection 154 - Connection 0.0.0.0:51211<->192.168.88.172:15010 shut down**

[Worker-2] org.apache.http.impl.conn.BasicClientConnectionManager 189 - Releasing connection org.apache.http.impl.conn.ManagedClientConnectionImpl@12f65ce5

DefaultClientConnection.shutdown (Връзка 0.0.0.0:51210‹-›192.168.88.172:15010 изключена) затваря ли връзката от края на клиента? Как се извиква? В кода след получаване на отговор (200OK) от сървъра httpPost.releaseConnection() се изпълнява само в код от страна на клиента.

Какво трябва да направя, за да поддържам връзките в състояние ESTABLISHED и да ги използвам повторно, вместо да създавам връзка за всяка заявка и те да преминават в TIME_WAIT.

Всяка помощ ще бъде високо оценена. Благодаря ти.




Отговори (2)


Забележете, че извикването на EntityUtils.console(entity) прави малко повече и трябва да се използва:

    /**
     * Ensures that the entity content is fully consumed and 
     * the content stream, if exists, is closed.
     *
     * @param entity the entity to consume.
     * @throws IOException if an error occurs reading the input stream
     *
     * @since 4.1
     */
    public static void consume(final HttpEntity entity) throws IOException {
        if (entity == null) {
            return;
        }
        if (entity.isStreaming()) {
            final InputStream inStream = entity.getContent();
            if (inStream != null) {
                inStream.close();
            }
        }
    }
person Christophe Roussy    schedule 13.08.2020

Проблемът беше разрешен преди няколко дни.

Грешка: извикване на releaseConnection() на обекта HttpClient. НО избягването му също не реши проблема.

Корекция: Действието, което трябваше да се предприеме за поддържане на връзките живи (в състояние ESTABLISHED) беше чрез следния примерен код:

HttpClient client = new org.apache.http.impl.client.DefaultHttpClient();
...
org.apache.http.HttpResponse response = client.executed(HttpPost) ;
org.apache.http.HttpEntity en = response.getEntity();
if (en != null) {
  en.getContent().close();
}

След като се получи HttpResponse, за да се използва повторно и поддържа създадената връзка, е необходимо да се затвори само InputStream (en.getContent()) на http-отговора. Не извиквайте друг метод за освобождаване на HttpPost или клиентски обекти.

Тествах тази работа с JMeter натоварване и установих, че работи. Все още не съм забелязал странични ефекти!

person pvg    schedule 07.05.2013
comment
EntityUtils.consume(entity) също ще го направи. - person Ashwin Jayaprakash; 08.04.2014
comment
EntityUtils.consume(entity) се справя по-добре и трябва да се използва, вижте отговора ми - person Christophe Roussy; 17.08.2020