Тайм-аут Java HttpRequest неожиданно выбрасывает HttpConnectTimeoutException - PullRequest
0 голосов
/ 19 декабря 2018

Используя новый пакет java.net.http, выпущенный с JDK 11, HttpRequest был собран с намеренно низким временем ожидания ответа:

HttpRequest.Builder builder = HttpRequest.newBuilder(getEndpointUri());
addRequestHeaders(builder);
builder.POST(HttpRequest.BodyPublishers.ofString(rawXml));
builder.timeout(Duration.ofMillis(1));
HttpRequest httpRequest = builder.build();

Цель состоит в том, чтобы проверить, что HttpTimeoutException результаты обработаныправильно, но неожиданно это значение времени ожидания ответа приводит к HttpConnectionTimeoutException, который перехватывается этим кодом:

try {
    HttpResponse<InputStream> httpResponse = completableExchange.join();
} catch (CompletionException ce) {
    if (ce.getCause() instanceof HttpConnectTimeoutException) {
        System.out.println("Connection timeout occurred!");
    } else {
        throw ce;
    }
}

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

Трассировка стека, прикрепленная к HttpConnectionTimeoutException, выглядит следующим образом:

java.net.http.HttpConnectTimeoutException: HTTP connect timed out
    at java.net.http/jdk.internal.net.http.ResponseTimerEvent.handle(ResponseTimerEvent.java:68)
    at java.net.http/jdk.internal.net.http.HttpClientImpl.purgeTimeoutsAndReturnNextDeadline(HttpClientImpl.java:1248)
    at java.net.http/jdk.internal.net.http.HttpClientImpl$SelectorManager.run(HttpClientImpl.java:877)
Caused by: java.net.ConnectException: HTTP connect timed out
    at java.net.http/jdk.internal.net.http.ResponseTimerEvent.handle(ResponseTimerEvent.java:69)
    ... 2 more

Я неправильно понимаю концепции тайм-аута?Предоставляет ли значение тайм-аута HttpRequest просто альтернативу значению тайм-аута HttpClient по умолчанию?Есть ли надежный способ отловить время ожидания соединения и ответа как отдельные события?

Для чего это стоит, Javadoc для HttpRequest.Builder.timeout(Duration) говорит следующее:

Устанавливает время ожидания для этогозапрос.Если ответ не получен в течение указанного времени ожидания, HttpTimeoutException генерируется из HttpClient :: send или HttpClient :: sendAsync, который завершается исключительно с HttpTimeoutException.Эффект не установки тайм-аута такой же, как и установка бесконечной длительности, т.е.навсегда.

Чтобы запутать, HttpConnectionTimeoutException является подклассом HttpTimeoutException, поэтому технически контракт метода timeout(Duration) выполняется.Но это кажется бесполезным.

(Прежде чем вы спросите: да, значение, переданное в HttpRequest.Builder.timeout(Duration), является решающим фактором в том, будет ли выброшено исключение. Таким образом, исключение не основано на значении времени ожидания соединения.используется для создания HttpClient экземпляра.)

1 Ответ

0 голосов
/ 17 января 2019

IIRC вы получите HttpConnectionTimeoutException, если соединение не подключено во время истечения времени ожидания или если истекло время ожидания соединения до завершения соединения.

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

Есть ли у вас какие-либо конкретные варианты использования для различения двух случаев:

  1. HttpConnectionTimeoutException повышен, поскольку соединение можетне подключаться в течение времени, указанного в тайм-ауте соединения,
  2. HttpConnectionTimeoutException повышен, потому что истекло время ожидания запроса до того, как соединение может быть установлено?
...