当 .timeout(Duration.ofSeconds(requestTimeout)) 发生时,会打印下面的消息
错误 [parallel-6] com.www.xyz.bbb.restv2retry.RestV2ServiceImpl:888 - 在“retryWhen”的 80000 毫秒内没有观察到任何项目或终端信号(并且未配置回退)
我收到消息是因为在向某个服务器调用 api 时发生了超时并且响应没有返回,但我想在发生超时时重试,因此在 retryPolicy() 方法中我使用了条件 || throwable.getCause() instanceof 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())));
}
}
即使超时也需要重试
问题已解决。 我改变了两件事。
谢谢@amanin,是的,先更改订单后
.timeout(Duration.ofSeconds(requestTimeout)) then
.retryWhen(retryPolicy())
它要重试。
throwable.getCause() instanceof TimeoutException
- 我在这里使用
io.netty.handler.timeout.TimeoutException
但实际上是这样
java.util.concurrent.TimeoutException
将 if 条件更改为
后有效throwable instanceof HttpServerErrorException
|| throwable instanceof WebClientRequestException
|| throwable instanceof TimeoutException;