java 发生超时异常时,Sping Boot webClient onErrorMap从未调用

zc0qhyus  于 2023-10-14  发布在  Java
关注(0)|答案(1)|浏览(134)

我有两个微服务user-ms和post-ms,user-ms调用post-ms来获取某个用户的posts计数。
在post-ms中,我强制延迟7秒以查看user-ms的行为。
下面是user-ms内部的方法

public Mono<PostsCountResponse> getPostsCountByUserUuid(UUID userUuid, int delay, int faultPercent) {

        URI url = UriComponentsBuilder.fromUriString(propertiesConfig.getVirtualPostServiceUrl()
                  + "/posts/count?userUuid={userUuid}&delay={delay}&faultPercent={faultPercent}").build(userUuid, delay, faultPercent);

        logger.info("Will call the findPostsCount API on URL: {}", url);
        
        return webClient.get().uri(url).accept(MediaType.APPLICATION_JSON).retrieve()
                .bodyToMono(PostsCountResponse.class)
                .onErrorMap(WebClientResponseException.class, ex -> handleException(ex));
                
    }

    private Throwable handleException(Throwable ex) {

        logger.info("starting handleException()..");

        if (!(ex instanceof WebClientResponseException)) {
            logger.warn("Got a unexpected error: {}, will rethrow it", ex.toString());
            return ex;
        }

        WebClientResponseException wcre = (WebClientResponseException) ex;

        switch (wcre.getStatusCode()) {

        case NOT_FOUND:
            return new NotFoundException(getErrorMessage(wcre));

        case UNPROCESSABLE_ENTITY:
            return new InvalidInputException(getErrorMessage(wcre));

        default:
            logger.warn("Got an unexpected HTTP error: {}, will rethrow it", wcre.getStatusCode());
            logger.warn("Error body: {}", wcre.getResponseBodyAsString());
            return ex;
        }
    }

一个超时异常发生在user-ms内部,但我不知道为什么onErrorMap从来没有被调用??
因此,我问题是,当我想使用Exception方法处理超时异常时,为什么不调用onErrorMap?
以下是来自user-ms:-

instagram-clone-insta-ms-user-info-1  | 2023-05-09 21:50:10.358  INFO 1 --- [nio-8080-exec-5] c.j.i.u.i.PostServiceIntegrationImpl     : Will call the findPostsCount API on URL: http://post-ms/posts/count?userUuid=aeb7f3e9-3e66-4ad8-9bd4-15f2b6a09a7a&delay=7&faultPercent=0
instagram-clone-insta-ms-user-info-1  | 2023-05-09 21:50:12.363 ERROR 1 --- [nio-8080-exec-5] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is reactor.core.Exceptions$ReactiveException: java.util.concurrent.TimeoutException: Did not observe any item or terminal signal within 2000ms in 'onErrorResume' (and no fallback has been configured)] with root cause
instagram-clone-insta-ms-user-info-1  |
instagram-clone-insta-ms-user-info-1  | java.util.concurrent.TimeoutException: Did not observe any item or terminal signal within 2000ms in 'onErrorResume' (and no fallback has been configured)
instagram-clone-insta-ms-user-info-1  |         at reactor.core.publisher.FluxTimeout$TimeoutMainSubscriber.handleTimeout(FluxTimeout.java:294) ~[reactor-core-3.4.7.jar:3.4.7]
instagram-clone-insta-ms-user-info-1  |         at reactor.core.publisher.FluxTimeout$TimeoutMainSubscriber.doTimeout(FluxTimeout.java:279) ~[reactor-core-3.4.7.jar:3.4.7]
instagram-clone-insta-ms-user-info-1  |         at reactor.core.publisher.FluxTimeout$TimeoutTimeoutSubscriber.onNext(FluxTimeout.java:418) ~[reactor-core-3.4.7.jar:3.4.7]
instagram-clone-insta-ms-user-info-1  |         at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79) ~[reactor-core-3.4.7.jar:3.4.7]
instagram-clone-insta-ms-user-info-1  |         at reactor.core.publisher.MonoDelay$MonoDelayRunnable.propagateDelay(MonoDelay.java:270) ~[reactor-core-3.4.7.jar:3.4.7]
instagram-clone-insta-ms-user-info-1  |         at reactor.core.publisher.MonoDelay$MonoDelayRunnable.run(MonoDelay.java:285) ~[reactor-core-3.4.7.jar:3.4.7]
instagram-clone-insta-ms-user-info-1  |         at reactor.core.scheduler.SchedulerTask.call(SchedulerTask.java:68) ~[reactor-core-3.4.7.jar:3.4.7]
instagram-clone-insta-ms-user-info-1  |         at reactor.core.scheduler.SchedulerTask.call(SchedulerTask.java:28) ~[reactor-core-3.4.7.jar:3.4.7]
instagram-clone-insta-ms-user-info-1  |         at java.base/java.util.concurrent.FutureTask.run(Unknown Source) ~[na:na]
instagram-clone-insta-ms-user-info-1  |         at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) ~[na:na]
instagram-clone-insta-ms-user-info-1  |         at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) ~[na:na]
instagram-clone-insta-ms-user-info-1  |         at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) ~[na:na]
instagram-clone-insta-ms-user-info-1  |         at java.base/java.lang.Thread.run(Unknown Source) ~[na:na]
instagram-clone-insta-ms-user-info-1  |

的日志

kknvjkwl

kknvjkwl1#

您期望看到的TimeoutException并没有扩展WebClientResponseException,这就是为什么没有调用handleException方法。
必须添加onErrorMap(TimeoutException.class, ...)
您还可以使用fallback方法从调用方设置超时:.timeout(Duration timeout, Mono<?> fallback)

相关问题