API调用错误:8000ms内没有观察到任何项目或终端信号(且未配置回退)/Spring WebClient/超时后重试

问题描述 投票:0回答:1

当 .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())));
    }
}

即使超时也需要重试

java spring spring-webflux
1个回答
0
投票

问题已解决。 我改变了两件事。

谢谢@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;
© www.soinside.com 2019 - 2024. All rights reserved.