Используя новый пакет 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
экземпляра.)