Httpclient по умолчанию для resttemplate, имеет абсолютное значение для тайм-аута чтения - PullRequest
1 голос
/ 20 мая 2019

У меня проблема в том, что приложение продолжает блокировать на неопределенный срок пост-вызов, сделанный с помощью RestTemplate из Spring Boot.

ResponseEntity<String> response = restTemplate.postForEntity(destination.getUri(), request, String.class);

Мы используем стандартную реализацию JDK по умолчанию и создаем ее так:

    this.restTemplate = restTemplateBuilder
                       .setConnectTimeout(5000)
                       .setReadTimeout(5000)
                       .build();

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

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

Я не могу найти что-то подобное в настройках клиента по умолчанию?

--- EDIT ---

Я попытался ответить @Peekay, но это не такКажется, не работает:

    CloseableHttpClient httpClient = HttpClientBuilder.create()
           .setConnectionTimeToLive(1, TimeUnit.SECONDS)
           .setConnectionManager(new PoolingHttpClientConnectionManager())
           .build();

   HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
   clientHttpRequestFactory.setHttpClient(httpClient);
   return new RestTemplate(clientHttpRequestFactory);

Я также пробовал различные реализации RestTemplate клиента, например HttpComponentsClientHttp, Netty4Client и OkHttp3Client создали их так:

    Netty4ClientHttpRequestFactory factory = new Netty4ClientHttpRequestFactory();
    factory.setConnectTimeout(timeout);
    factory.setReadTimeout(readTimeout);
    return new RestTemplate(factory);

И проверил их на ответ, который занял больше 5 секунд.Все они, кроме Нетти, которая вернула ReadTimeoutException, вернули 200 успехов.К сожалению, я не могу переключиться на этот клиент, кажется, вам нужно реализовать его самостоятельно, если вы хотите продолжать использовать клиент по умолчанию.

Ответы [ 3 ]

1 голос
/ 20 мая 2019

Вы правы, вы не можете установить абсолютное значение и вам нужно прервать сам протектор.

0 голосов
/ 19 июня 2019

Мы исправили это, заключив вызов RestTemplate REST в CompletableFuture и используя функцию тайм-аута из этой оболочки, чтобы завершить поток, если это займет слишком много времени.

Вот пример:

CompletableFuture<T> requestWrapper = CompletableFuture.supplyAsync(() -> {
  return restTemplate.postForEntity(/* Whatever arguments you need to pass */);
});

try {
  return requestWrapper.get(5000, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
  requestWrapper.cancel(true);
  throw new TimeoutException("Endpoint took too long to respond, TimeoutException is triggered");
} catch (ExecutionException e) {
  throw e.getCause();
}
0 голосов
/ 20 мая 2019

Вы можете использовать альтернативные http-клиенты с RestTemplate, например, Apache HttpClient , который дает вам больше контроля над настройкой, пулированием и поддержанием соединений:

  • ОтHttpClientBuilder Вы можете установить время жизни соединения, которое является максимальным TTL для соединения
  • . Вы можете определить RequestConfig, указав время ожидания соединения (максимальное время ожиданиядля установления соединения) и отдельное время ожидания сокета (максимальное время чтения () будет ожидать данных).

Для получения дополнительной информации см .: setConnectTimeout vs. setConnectionTimeToLive против setSocketTimeout ()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...