Мои выводы
Установка тайм-аута определенным образом для клиента http приведет к исключению, специфичному для клиента http, т.е. WebClient
не переносит исключения:
@Test
void test() {
var host = "localhost";
var endpoint = "/test";
var port = 8089;
var timeout = Duration.ofSeconds(3);
WireMockServer wireMockServer = new WireMockServer(wireMockConfig().port(8089));
wireMockServer.start();
WireMock.configureFor(host, wireMockServer.port());
WireMock.stubFor(get(urlEqualTo(endpoint))
.willReturn(aResponse().withFixedDelay((int) timeout.toMillis())));
HttpClient httpClient = HttpClient.create()
.tcpConfiguration(client ->
client.doOnConnected(conn -> conn
.addHandlerLast(new ReadTimeoutHandler((int) (timeout.toSeconds() / 2)))
.addHandlerLast(new WriteTimeoutHandler((int) (timeout.toSeconds() / 2)))));
WebClient webClient = WebClient.builder()
.baseUrl(format("http://%s:%d", host, port))
.clientConnector(new ReactorClientHttpConnector(httpClient)).build();
webClient.get().uri(endpoint).retrieve().bodyToMono(Recommendation.class).block();
}
Это приведет к io.netty.handler.timeout.ReadTimeoutException
.
.timeout(timeout.dividedBy(2)).block()
приведет к обычному TimeoutException
(java.util.concurrent
), но все еще остается открытым вопрос, заботится ли веб-клиент о соединениях впоследствии (вероятно, нет).
Мое решение состоит в том, чтобы использовать специальную конфигурацию http-клиента, чтобы обеспечить собственный и правильный способ использования соединений, при этом добавляя новый обработчик, который оборачивает исключение, связанное с http-клиентом, в более общие (или java.util.concurrent.TimeoutException
), чтобы клиенты WebClient
не будет зависеть от исключений провайдера.