如何使单声道超时有效

时间:2019-01-23 14:20:13

标签: spring-webflow project-reactor

我首先在项目中使用webflux,只是想在长时间处理的情况下设置超时时间。

@GetMapping("/{id}")
private Mono<ResponseEntity<String>> getEmployeeById(@PathVariable 
String id) {
    return Mono.just(id).map(updateTweet -> {
        try {
            TimeUnit.SECONDS.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return new ResponseEntity<>(updateTweet, HttpStatus.OK);
    }).timeout(Duration.ofSeconds(3)).onErrorReturn(new ResponseEntity<>("0000", HttpStatus.OK));

}

期望:3秒钟后,此函数将返回。 实际结果:10秒钟后,此函数返回。

2 个答案:

答案 0 :(得分:1)

TimeUnit.SECONDS.sleep(10)的作用是调用Thread.sleep()。这把当前 进入睡眠模式10秒钟。

由于您是在map内执行此操作,因此进入睡眠状态的线程是当前线程。等待timeOut的代码也位于当前线程上,因此直到sleep超时后才生效。因此,在进行反应式编程时,应避免执行任何与Thread相关的操作。

如果要在上述代码中模拟长时间运行的过程,则可以调用受您控制的外部API,该API在发送响应之前等待3秒以上,或者使用delay*运算符之一。

答案 1 :(得分:0)

在您的代码中,.map.timeout都在订阅线程中。 .sleep(10)导致当前正在执行的线程进入10s的睡眠状态(暂时停止执行)。因此,3s超时后,线程将无法执行。

您应该使用 publishOn .map移至调度程序线程。

@GetMapping("/{id}")
private Mono<ResponseEntity<String>> getEmployeeById(@PathVariable 
String id) {
    Scheduler singleThread = Schedulers.single();
    return Mono.just(id).publishOn(singleThread).map(updateTweet -> {
        try {
            TimeUnit.SECONDS.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return new ResponseEntity<>(updateTweet, HttpStatus.OK);
    }).timeout(Duration.ofSeconds(3)).onErrorReturn(new ResponseEntity<>("0000", HttpStatus.OK));

}