Когда происходит .timeout(Duration.ofSeconds(requestTimeout)) ниже, печатается сообщение
ОШИБКА [parallel-6] com.www.xyz.bbb.restv2retry.RestV2ServiceImpl:888 — не обнаружено ни одного элемента или сигнала терминала в течение 80 000 мс в режиме «retryWhen» (и резервный вариант не настроен).
я получаю сообщение, потому что при вызове API на какой-то сервер произошел тайм-аут, и ответ не пришел, но я хочу повторить попытку, когда наступит тайм-аут, поэтому внутри метода retryPolicy() я использовал условие || throwable.getCause() экземпляр TimeoutException, чтобы повторить попытку, когда наступит тайм-аут, но все еще не работает.
Есть идеи, как повторить попытку после тайм-аута?
Ниже приведен код
@Service
public class RestV2ServiceImpl implements RestV2Service {
private static final Logger LOGGER = LoggerFactory.getLogger(RestV2ServiceImpl.class);
@Value("${apirest.server.requestTimeoutInSeconds}")
private Long requestTimeout;
@Value("${retryPolicy.maxAttempts}")
private Integer restV2retryPolicyMaxAttempts;
@Value("${retryPolicy.periodInMilliseconds}")
private Long restV2initialInterval;
@Autowired
private WebClient webClient;
@Override
public String updateRequestV2(String url, String requestJson, String versionSequence) {
return webClient.patch()
.uri(url)
.header(HttpHeaders.CONTENT_TYPE, "application/json-patch+json")
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
.header("If-Match", versionSequence)
.body(BodyInserters.fromValue(requestJson))
.retrieve()
.onStatus(this::retryableStatuses, this::retryableStatusException)
.bodyToMono(String.class)
.retryWhen(retryPolicy())
.timeout(Duration.ofSeconds(requestTimeout))
.doOnError(throwable -> LOGGER.error(throwable.getMessage()))
.block();
}
/**
* Return the range of HTTP codes for which REST v2 requests should be retried.
* @param status HttpStatus returned from a REST call
* @return true if request should be retried
*/
private boolean retryableStatuses(HttpStatus status) {
return status.is5xxServerError();
}
/**
* Creates an exception to be analyzed by the "retryWhen(...)" method to indicate
* conditions for which a request should be retried.
* @param response HTTP response from the latest REST request
* @return
*/
private Mono<? extends Throwable> retryableStatusException(ClientResponse response) {
return response.bodyToMono(String.class).map(body ->
new HttpServerErrorException(response.statusCode(), body));
}
/**
* Defines the policy for retrying a REST request.
* This policy retries on HttpServerErrorException created by the retryableStatusException
* method (which defines retryable server side errors) and on WebClientRequestException which defines
* client side errors prior to processing a request (e.g. certain request timeouts).
* @return the policy
*/
private Retry retryPolicy() {
return Retry.backoff(restV2retryPolicyMaxAttempts, Duration.ofMillis(restV2initialInterval))
.filter(throwable -> throwable instanceof HttpServerErrorException || throwable instanceof WebClientRequestException || || throwable.getCause() instanceof TimeoutException)
.onRetryExhaustedThrow(((retryBackoffSpec, retrySignal) -> new RetryExhaustedException(retrySignal.failure().getMessage())));
}
}
Необходимо повторить попытку, даже если истекло время ожидания




Проблема решена. Было 2 вещи, которые я изменил.
Спасибо @amanin, да, после изменения порядка, так что сначала
.timeout(Duration.ofSeconds(requestTimeout)) then
.retryWhen(retryPolicy())
это собиралось повторить попытку.
throwable.getCause() instanceof TimeoutException - здесь я использовал
io.netty.handler.timeout.TimeoutException но на самом деле это было
java.util.concurrent.TimeoutException
Работало После изменения условия на
throwable instanceof HttpServerErrorException
|| throwable instanceof WebClientRequestException
|| throwable instanceof TimeoutException;
Порядок операторов имеет значение. Если вы установите тайм-аут после повторной попытки, он будет иметь приоритет над механизмом повторной попытки. Но если вы поставите повторную попытку после, то при наступлении таймаута стратегия повтора получит ошибку таймаута и затем сможет повторить попытку.