Spring webflux Flux(WebClient)并行调用,然后对收集的列表进行后期处理

Spring webflux Flux(WebClient)并行调用,然后对收集的列表进行后期处理,spring-webflux,project-reactor,Spring Webflux,Project Reactor,我有一个用例,我需要在10个上游系统的并行调用上运行WebClient,超时为450ms,很少有上游系统会给出80-150ms的p99延迟,很少有系统会花费约300ms在这里,我需要收集每个人的数据,然后进行排名。这里我需要一个建议,如果我使用Collect()然后进行排名,可能会阻塞线程,因为我需要先从所有人那里获取数据,然后进行排名。有人能解释一下这里的线程流吗?提前谢谢 示例1: Flux.just("red", "white", "blu

我有一个用例,我需要在10个上游系统的并行调用上运行WebClient,超时为450ms,很少有上游系统会给出80-150ms的p99延迟,很少有系统会花费约300ms在这里,我需要收集每个人的数据,然后进行排名。这里我需要一个建议,如果我使用Collect()然后进行排名,可能会阻塞线程,因为我需要先从所有人那里获取数据,然后进行排名。有人能解释一下这里的线程流吗?提前谢谢

示例1:

Flux.just("red", "white", "blue")
        .log()
        .map(String::toUpperCase)
        .subscribe(System.out::println);

Output:

17:02:18.479 [main] INFO reactor.Flux.Array.1 - | onSubscribe([Synchronous Fuseable] FluxArray.ArraySubscription)
17:02:18.483 [main] INFO reactor.Flux.Array.1 - | request(unbounded)
17:02:18.483 [main] INFO reactor.Flux.Array.1 - | onNext(red)
RED
17:02:18.484 [main] INFO reactor.Flux.Array.1 - | onNext(white)
WHITE
17:02:18.484 [main] INFO reactor.Flux.Array.1 - | onNext(blue)
BLUE
17:02:18.485 [main] INFO reactor.Flux.Array.1 - | onComplete()
Flux.just("red", "white", "blue")
        .log()
        .map(String::toUpperCase)
        .collectList()
        .subscribe(System.out::println);

Output:

17:03:10.556 [main] DEBUG reactor.util.Loggers$LoggerFactory - Using Slf4j logging framework
17:03:10.622 [main] INFO reactor.Flux.Array.1 - | onSubscribe([Synchronous Fuseable] FluxArray.ArraySubscription)
17:03:10.625 [main] INFO reactor.Flux.Array.1 - | request(unbounded)
17:03:10.626 [main] INFO reactor.Flux.Array.1 - | onNext(red)
17:03:10.626 [main] INFO reactor.Flux.Array.1 - | onNext(white)
17:03:10.626 [main] INFO reactor.Flux.Array.1 - | onNext(blue)
17:03:10.627 [main] INFO reactor.Flux.Array.1 - | onComplete()
[RED, WHITE, BLUE]
示例2:

Flux.just("red", "white", "blue")
        .log()
        .map(String::toUpperCase)
        .subscribe(System.out::println);

Output:

17:02:18.479 [main] INFO reactor.Flux.Array.1 - | onSubscribe([Synchronous Fuseable] FluxArray.ArraySubscription)
17:02:18.483 [main] INFO reactor.Flux.Array.1 - | request(unbounded)
17:02:18.483 [main] INFO reactor.Flux.Array.1 - | onNext(red)
RED
17:02:18.484 [main] INFO reactor.Flux.Array.1 - | onNext(white)
WHITE
17:02:18.484 [main] INFO reactor.Flux.Array.1 - | onNext(blue)
BLUE
17:02:18.485 [main] INFO reactor.Flux.Array.1 - | onComplete()
Flux.just("red", "white", "blue")
        .log()
        .map(String::toUpperCase)
        .collectList()
        .subscribe(System.out::println);

Output:

17:03:10.556 [main] DEBUG reactor.util.Loggers$LoggerFactory - Using Slf4j logging framework
17:03:10.622 [main] INFO reactor.Flux.Array.1 - | onSubscribe([Synchronous Fuseable] FluxArray.ArraySubscription)
17:03:10.625 [main] INFO reactor.Flux.Array.1 - | request(unbounded)
17:03:10.626 [main] INFO reactor.Flux.Array.1 - | onNext(red)
17:03:10.626 [main] INFO reactor.Flux.Array.1 - | onNext(white)
17:03:10.626 [main] INFO reactor.Flux.Array.1 - | onNext(blue)
17:03:10.627 [main] INFO reactor.Flux.Array.1 - | onComplete()
[RED, WHITE, BLUE]
在示例2中,我添加了
.collectList()

示例#3

    public Mono<List<String>> fetchUsers(List<String> userIds) {
        return Flux.fromIterable(userIds)
            .subscribeOn(Schedulers.elastic())
            .flatMap(this::getUser)
            .collectList();
    }

    // This will be an HTTP Call p99 latency 450 ms
    public Mono<String> getUser(String id) {
        return webClient.get()
             .uri("/user/{id}", id)
             .retrieve()
             .bodyToMono(String.class);
    }
公共用户(列出用户ID){
返回通量.fromIterable(userid)
.subscribeOn(Schedulers.elastic())
.flatMap(this::getUser)
.collectList();
}
//这将是一个HTTP调用p99延迟450毫秒
公共用户(字符串id){
返回webClient.get()
.uri(“/user/{id}”,id)
.retrieve()
.bodyToMono(String.class);
}

一些示例代码可能会很有用。收集运算符是非阻塞的。不确定排名在您的域中意味着什么,但如果它只是内存字段中的排序依据,那也没关系。@MartinTarjányi添加了一个示例代码供参考,这里的排名是指列表中有一些属性,我需要用于自定义排名。因此,对于每个onNext(),线程都不会被阻塞?返回到事件循环并执行其他任务,当另一个事件再次出现时,同一线程将收到通知并处理下一个onNext(),直到onComplete()/onError()?@MartinTarjányi添加了示例#3和collect()和并行调用…这里的并行调用我指的是网络I/ORight,没有阻塞。甚至
subscribeOn(Schedulers.elastic())
都是不必要的,因为这里不涉及阻塞I/O。@MartinTarjányi感谢Martin的确认,
getUser()
我刚才添加的代码仅供参考,这将是我正在解决的网络I/O问题。我在方法的上方添加了注释,以供参考。一些示例代码可能会很有用。收集运算符是非阻塞的。不确定排名在您的域中意味着什么,但如果它只是内存字段中的排序依据,那也没关系。@MartinTarjányi添加了一个示例代码供参考,这里的排名是指列表中有一些属性,我需要用于自定义排名。因此,对于每个onNext(),线程都不会被阻塞?返回到事件循环并执行其他任务,当另一个事件再次出现时,同一线程将收到通知并处理下一个onNext(),直到onComplete()/onError()?@MartinTarjányi添加了示例#3和collect()和并行调用…这里的并行调用我指的是网络I/ORight,没有阻塞。甚至
subscribeOn(Schedulers.elastic())
都是不必要的,因为这里不涉及阻塞I/O。@MartinTarjányi感谢Martin的确认,
getUser()
我刚才添加的代码仅供参考,这将是我正在解决的网络I/O问题。我在方法上方添加了注释,仅供参考。