简体   繁体   English

Spring Flux和异步注释

[英]Spring Flux and the Async annotation

I have a Spring Flux application where at some point I need to execute some heavy task on the background, the caller (a HTTP request) does not need to wait until that task completes. 我有一个Spring Flux应用程序,在某个时候我需要在后台执行一些繁重的任务,调用者(一个HTTP请求)不需要等待该任务完成。

Without reactor, I would just probably use the Async annotation, executing that method on a different thread. 没有反应堆,我可能只是使用Async注释,在另一个线程上执行该方法。 With reactor, I am not sure if I should proceed with that approach or if there is already a built-in mechanism that allows me to accomplish this. 对于Reactor,我不确定是否应该继续使用该方法,或者不确定是否已有内置机制可以实现这一目标。

For example, given a Controller that accepts a Resource object: 例如,给定一个接受Resource对象的Controller

@PostMapping("/create")
public Mono<Resource> create(@Valid @RequestBody Resource r) {
    processor.run(r); // the caller should not wait for the resource to be processed
    return repository.save(r);
}

And a Processor class: 和一个处理器类:

@Async
void run(Resource r) { 
    WebClient webClient = WebClient.create("http://localhost:8080");
    Mono<String> result = webClient.get()
                                   .retrieve()
                                   .bodyToMono(String.class);
    String response = result.block(); //block for now
}

The HTTP caller for /create should not need to wait until the run method completes. /create的HTTP调用程序无需等待run方法完成即可。

If you are looking for the fire-and-forget pattern implementation, you could just subscribe your publisher 如果您正在寻找即弃模式的实现,则可以订阅发布者

@PostMapping("/create")
public Mono<Resource> create(@Valid @RequestBody Resource r) {
    run(r).subscribe();
    return repository.save(r);
}

Mono<Void> run(Resource r) {
    WebClient webClient = WebClient.create("http://localhost:8080");
    return webClient.get()
            .retrieve()
            .bodyToMono(String.class)
            .then();
}

If your publisher executes blocking operations it should be subscribed on other thread with elastic or parallel scheduler. 如果您的发布者执行阻止操作,则应使用弹性或并行调度程序在其他线程上进行订阅。

I did some testing, and I think even using subscribe() as fire and forget will wait for request to complete before returning an answer to the webbrowser or REST-client (at least in my simple tests, it looks like that). 我进行了一些测试,我认为即使将subscribe()用作触发方式,也忘记了要等待请求完成,然后再将答案返回给Webbrowser或REST客户端(至少在我的简单测试中,它看起来像这样)。 So, you have to do the similar of @Async, create another thread: 因此,您必须执行类似@Async的操作,并创建另一个线程:

@PostMapping("/create")
public Mono<Resource> create(@Valid @RequestBody Resource r) {
    return processor.run(r)
    .subscribeOn(Schedulers.elastic()) // put eveything above this line on another thread
    .doOnNext(string -> repository.save(r)); // persist "r", not changing it, though

}

And a Processor class: 和一个处理器类:

Mono<String> run(Resource r) { 
    WebClient webClient = WebClient.create("http://localhost:8080");
    return webClient.get()
           .retrieve()
           .bodyToMono(String.class);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM