Тайм-аут HttpClient

HttpClient Timeout

1. обзор

Из этого туториала Вы узнаете, какconfigure a timeout with the Apache HttpClient 4.

Если вы хотите копнуть глубже и узнать о других интересных вещах, которые можно сделать с помощью HttpClient, перейдите кthe main HttpClient tutorial.

Дальнейшее чтение:

Управление соединениями HttpClient

Как открывать, управлять и закрывать соединения с Apache HttpClient 4.

Read more

HttpClient 4 - следуйте перенаправления для POST

Как включить POST Redirect с помощью Apache HttpClient.

Read more

Расширенная настройка HttpClient

Конфигурации HttpClient для расширенных вариантов использования.

Read more

2. Настройте тайм-ауты с помощью необработанных параметровString

HttpClient поставляется с множеством параметров конфигурации, и все они могут быть установлены обычным способом, подобным карте.

Есть3 timeout parameters to configure:

DefaultHttpClient httpClient = new DefaultHttpClient();

int timeout = 5; // seconds
HttpParams httpParams = httpClient.getParams();
httpParams.setParameter(
  CoreConnectionPNames.CONNECTION_TIMEOUT, timeout * 1000);
httpParams.setParameter(
  CoreConnectionPNames.SO_TIMEOUT, timeout * 1000);
httpParams.setParameter(
  ClientPNames.CONN_MANAGER_TIMEOUT, new Long(timeout * 1000));

3. Настроить тайм-ауты через API

Наиболее важные из этих параметров, а именно первые два, также можно установить с помощью более безопасного типа API:

DefaultHttpClient httpClient = new DefaultHttpClient();

int timeout = 5; // seconds
HttpParams httpParams = httpClient.getParams();
HttpConnectionParams.setConnectionTimeout(
  httpParams, timeout * 1000); // http.connection.timeout
HttpConnectionParams.setSoTimeout(
  httpParams, timeout * 1000); // http.socket.timeout

У третьего параметра нет специального установщика вHttpConnectionParams, и его все равно нужно будет установить вручную с помощью методаsetParameter.

4. Настройка таймаутов с использованием нового 4.3. строитель

Беглый строительный API, представленный в 4.3, предоставляетthe right way to set timeouts at a high level:

int timeout = 5;
RequestConfig config = RequestConfig.custom()
  .setConnectTimeout(timeout * 1000)
  .setConnectionRequestTimeout(timeout * 1000)
  .setSocketTimeout(timeout * 1000).build();
CloseableHttpClient client =
  HttpClientBuilder.create().setDefaultRequestConfig(config).build();

Это рекомендуемый способ настройки всех трех тайм-аутов безопасным и читаемым способом.

5. Объяснение свойств тайм-аута

Теперь давайте объясним, что означают эти различные типы тайм-аутов:

  • Connection Timeout (http.connection.timeout) - время установления соединения с удаленным хостом

  • Socket Timeout (http.socket.timeout) - время ожидания данных - после установления соединения; максимальное время бездействия между двумя пакетами данных

  • Connection Manager Timeout (http.connection-manager.timeout) - время ожидания соединения от диспетчера соединений / пула

Первые два параметра - время ожидания соединения и сокета - являются наиболее важными. Однако установка тайм-аута для получения соединения определенно важна в сценариях с высокой нагрузкой, поэтому не следует игнорировать третий параметр.

6. ИспользуяHttpClient

После его настройки мы можем использовать клиент для выполнения HTTP-запросов:

HttpGet getMethod = new HttpGet("http://host:8080/path");
HttpResponse response = httpClient.execute(getMethod);
System.out.println(
  "HTTP Status of response: " + response.getStatusLine().getStatusCode());

С ранее определенным клиентомthe connection to the host will time out in 5 seconds.. Кроме того, если соединение установлено, но данные не получены, таймаут также будет5 additional seconds.

Обратите внимание, что тайм-аут соединения приведет к выбросуorg.apache.http.conn.ConnectTimeoutException, а тайм-аут сокета приведет кjava.net.SocketTimeoutException.

7. Жесткий тайм-аут

Хотя установка таймаутов при установке HTTP-соединения и отсутствии данных очень полезна, иногда нам нужно установитьhard timeout for the entire request.

Например, загрузка потенциально большого файла вписывается в эту категорию. В этом случае соединение может быть успешно установлено, данные могут поступать постоянно, но нам все равно необходимо убедиться, что операция не превышает определенный временной порог.

HttpClient не имеет конфигурации, которая позволяет нам установить общий тайм-аут для запроса; однако он предоставляетabort functionality for requests, поэтому мы можем использовать этот механизм для реализации простого механизма тайм-аута:

HttpGet getMethod = new HttpGet(
  "http://localhost:8080/httpclient-simple/api/bars/1");

int hardTimeout = 5; // seconds
TimerTask task = new TimerTask() {
    @Override
    public void run() {
        if (getMethod != null) {
            getMethod.abort();
        }
    }
};
new Timer(true).schedule(task, hardTimeout * 1000);

HttpResponse response = httpClient.execute(getMethod);
System.out.println(
  "HTTP Status of response: " + response.getStatusLine().getStatusCode());

Мы используемjava.util.Timer иjava.util.TimerTask, чтобы настроитьsimple delayed task which aborts the HTTP GET request после 5-секундного жесткого тайм-аута.

8. Таймаут и циклический перебор DNS - кое-что, о чем следует знать

Довольно часто некоторые более крупные домены будут использовать конфигурацию циклического перебора DNS - по существу, сthe same domain mapped to multiple IP addresses. Это создает новую проблему для тайм-аута против такого домена просто из-за способа, которым HttpClient будет пытаться подключиться к этому домену, который истекает:

  • HttpClient получаетthe list of IP routes в этот домен

  • он пытаетсяthe first one - это время истекает (с установленными нами таймаутами)

  • он пытаетсяthe second one - это тоже время ожидания

  • и так далее …

Итак, как видите -the overall operation will not time out when we expect it to. Вместо этого - истечет время ожидания, когда все возможные маршруты истекли. Более того, это будет происходить полностью прозрачно для клиента (если у вас не настроен журнал на уровне DEBUG).

Вот простой пример, который вы можете запустить и воспроизвести эту проблему:

int timeout = 3;
RequestConfig config = RequestConfig.custom().
  setConnectTimeout(timeout * 1000).
  setConnectionRequestTimeout(timeout * 1000).
  setSocketTimeout(timeout * 1000).build();
CloseableHttpClient client = HttpClientBuilder.create()
  .setDefaultRequestConfig(config).build();

HttpGet request = new HttpGet("http://www.google.com:81");
response = client.execute(request);

Вы заметите логику повторных попыток с уровнем журнала DEBUG:

DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.google.com/173.194.34.212:81
DEBUG o.a.h.i.c.HttpClientConnectionOperator -
 Connect to www.google.com/173.194.34.212:81 timed out. Connection will be retried using another IP address

DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.google.com/173.194.34.208:81
DEBUG o.a.h.i.c.HttpClientConnectionOperator -
 Connect to www.google.com/173.194.34.208:81 timed out. Connection will be retried using another IP address

DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.google.com/173.194.34.209:81
DEBUG o.a.h.i.c.HttpClientConnectionOperator -
 Connect to www.google.com/173.194.34.209:81 timed out. Connection will be retried using another IP address
//...

9. Заключение

В этом руководстве обсуждалось, как настроить различные типы тайм-аутов, доступных дляHttpClient. Также проиллюстрирован простой механизм для жесткого таймаута текущего HTTP-соединения.

Реализацию этих примеров можно найти вthe GitHub project.