Spring WebFlux:未超时却触发Timeout Handler问题排查与解决
问题原因分析
你遇到的这个问题其实是个常见的Java方法调用陷阱——handler()方法在构建Mono链的时候就被立即执行了,而不是等到超时事件触发时才调用。
看你的代码:
.timeout(Duration.ofSeconds(100), handler())
这里的第二个参数要求是一个Mono<? extends Integer>,所以Java在执行这条语句时,会先计算handler()的返回值,也就是立刻调用handler(),打印出"handler invoked",然后把返回的Mono.just(10)传给timeout方法。
而实际的超时逻辑是:原Mono在1秒后就正常发射了元素,timeout判断没有超时,所以并不会切换到这个提前准备好的fallback Mono,最终订阅的还是原Mono的1,所以你会看到先打印handler invoked,再打印1。
实现预期行为的解决方案
要让handler()只在真正发生超时的时候才被调用,你需要使用timeout的另一个重载方法,它接受一个Supplier<Mono<? extends Integer>>(延迟提供fallback的接口),这样只有超时发生时,才会调用Supplier的get()方法来生成fallback Mono。
修改后的代码如下:
public static void main(String[] args) throws InterruptedException { Mono<Integer> integerMono = Mono.just(1).delayElement(Duration.ofSeconds(1)); integerMono // 改用Supplier,延迟调用handler() .timeout(Duration.ofSeconds(100), () -> handler()) .subscribe(integer -> System.out.println(integer)); Thread.sleep(10000); } private static Mono<? extends Integer> handler() { System.out.println("handler invoked"); return Mono.just(10); }
验证效果
修改后,原Mono在1秒后正常发射元素,不会触发超时逻辑,所以handler()不会被调用,输出只会是1。如果把原Mono的延迟改成101秒(超过100秒的超时时间),这时候才会触发handler(),输出handler invoked和10。
内容的提问来源于stack exchange,提问作者Rahul Gupta
相关产品推荐
相关产品推荐

