Перейти к основному содержимому

Тайм-аут Java HttpClient

· 3 мин. чтения

1. Обзор

В этом руководстве мы покажем, как настроить тайм-аут с новым HTTP-клиентом Java, доступным, начиная с Java 11, и пакетом Java.

Если нам нужно освежить наши знания, мы можем начать с учебника по HTTP-клиенту Java .

С другой стороны, чтобы узнать, как настроить тайм-аут с помощью старой библиотеки, см . HttpUrlConnection.

2. Настройка тайм-аута

Прежде всего, нам нужно настроить HttpClient, чтобы иметь возможность делать HTTP-запросы:

private static HttpClient getHttpClientWithTimeout(int seconds) {
return HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(seconds))
.build();
}

Выше мы создали метод, который возвращает HttpClient , настроенный с тайм-аутом, определенным в качестве параметра. Вкратце, мы используем шаблон проектирования Builder для создания экземпляра HttpClient и настройки времени ожидания с помощью метода connectTimeout . Кроме того, с помощью статического метода ofSeconds мы создали экземпляр объекта Duration , который определяет время ожидания в секундах.

После этого проверяем, правильно ли настроен таймаут HttpClient :

httpClient.connectTimeout().map(Duration::toSeconds)
.ifPresent(sec -> System.out.println("Timeout in seconds: " + sec));

Итак, мы используем метод connectTimeout для получения времени ожидания. В результате он возвращает необязательный параметр Duration, который мы сопоставили с секундами.

3. Обработка тайм-аутов

Далее нам нужно создать объект HttpRequest , который наш клиент будет использовать для выполнения HTTP-запроса:

HttpRequest httpRequest = HttpRequest.newBuilder()
.uri(URI.create("http://10.255.255.1")).GET().build();

Чтобы имитировать тайм-аут, мы делаем вызов на немаршрутизируемый IP-адрес. Другими словами, все TCP-пакеты отбрасываются и вызывают тайм-аут по истечении предопределенного времени, настроенного ранее.

Теперь давайте подробнее рассмотрим, как обрабатывать тайм-аут.

3.1. Обработка тайм-аута синхронного вызова

Например, чтобы сделать синхронный вызов, используйте метод send :

HttpConnectTimeoutException thrown = assertThrows(
HttpConnectTimeoutException.class,
() -> httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()),
"Expected send() to throw HttpConnectTimeoutException, but it didn't");
assertTrue(thrown.getMessage().contains("timed out"));

Синхронный вызов заставляет перехватывать исключение IOException , которое расширяет исключение HttpConnectTimeoutException . Следовательно, в приведенном выше тесте мы ожидаем HttpConnectTimeoutException с сообщением об ошибке.

3.2. Обработка времени ожидания асинхронного вызова

Точно так же, чтобы сделать асинхронный вызов, используйте метод sendAsync :

CompletableFuture<String> completableFuture = httpClient.sendAsync(httpRequest, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.exceptionally(Throwable::getMessage);
String response = completableFuture.get(5, TimeUnit.SECONDS);
assertTrue(response.contains("timed out"));

Приведенный выше вызов sendAsync возвращает CompletableFuture<HttpResponse> . Следовательно, нам нужно определить, как функционально обрабатывать ответ. Подробно, мы получаем тело из ответа, когда ошибок не возникает. В противном случае мы получим сообщение об ошибке от throwable. Наконец, мы получаем результат от CompletableFuture , подождав максимум 5 секунд. Опять же, этот запрос вызывает исключение HttpConnectTimeoutException , как мы и ожидали, сразу после 3 секунд.

4. Настройте тайм-аут на уровне запроса

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

HttpRequest httpRequest = HttpRequest.newBuilder()
.uri(URI.create("http://10.255.255.1"))
.timeout(Duration.ofSeconds(1))
.GET()
.build();

Точно так же мы используем метод тайм -аута , чтобы установить тайм-аут для этого запроса. Здесь мы настроили тайм-аут в 1 секунду для этого запроса.

Минимальная продолжительность между клиентом и запросом устанавливает время ожидания для запроса.

5. Выводы

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

И, как всегда, исходный код примеров доступен на GitHub .