Как установить и обработать тайм-аут в Spring WebClient? - PullRequest
0 голосов
/ 17 февраля 2019

Spring docs говорит, что необходимо настроить http-клиент для WebClient вручную, чтобы установить тайм-ауты: https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-client-builder-reactor-timeout. Но поскольку WebClient возвращает реактивный Mono, возможно (по возможности) применить метод .timeout.

Имеет ли он тот же эффект?

Более того, когда используется метод .timeout, ожидается использование Reactor's TimeoutException.Появится ли такая же ошибка в потоке, если настройка будет выполнена вручную, т.е. будет работать doOnError(TimeoutException.class, ...)?

1 Ответ

0 голосов
/ 20 февраля 2019

Мои выводы

Установка тайм-аута определенным образом для клиента 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не будет зависеть от исключений провайдера.

...