助焊剂flatMap背压

时间:2019-07-03 11:34:33

标签: java project-reactor

如何施加反压来限制Publisher产生的项目比并行运行的flatMap可以处理的更多?

1。设置

出于说明目的,有一个快速的Twitter用户名生成器,一个缓慢的Twitter查找调用,一个缓慢的Twitter文件编写器和一种打印方法。

private Consumer<FluxSink<String>> twitterUsernameGenerator() {
    return (sink) -> Stream.of("a", "b", "c", "d").forEach(sink::next);
}

private Flux<TwitterMessage>findTwitterMessagesByUsername() {
    return Flux.create(sink -> {
            sink.next(new TwitterMessage(...));
            sleep(2000);
            sink.next(new TwitterMessage(...));
        }
    });
}

private void print(Object o) {
    System.out.println("[" + Thread.currentThread().getName() + "] " + o);
}

最终目标是在对生成器施加反压的同时并行运行Twitter查找,以使用户名不会超出可处理的范围(预计会进行一些预取)。

2。生成Twitter用户名

Flux.create(twitterUsernameGenerator())
    .publishOn(Schedulers.single())
    .doOnNext(this::print)
    .subscribe();

这可以在一个单独的线程上很好地产生5个Twitter用户名

[single-1] a
[single-1] b
[single-1] c
[single-1] d

3。查找Twitter消息

不确定它是否正确,但我认为flatMap从一个用户名生成许多Twitter消息,而parallel在两个线程上执行此 I / O密集操作。

Flux.create(twitterUsernameGenerator())
    .publishOn(Schedulers.single())
    .doOnNext(this::print)
    .parallel(2)
    .runOn(Schedulers.newParallel("p", 2))
    .flatMap(username -> findTwitterMessagesByUsername(username))
    .doOnNext(this::print)
    .subscribe();

哇!生成器生成用户名的速度比我们处理的速度更快。

[single-1] a
[single-1] b
[single-1] c
[single-1] d
[p-1] TwitterMessage{...}
[p-2] TwitterMessage{...}
...

3。向发电机施加背压

如何对发生器功能施加反压,以使结果更接近于此

[single-1] a
[single-1] b
[p-1] TwitterMessage{...}
[single-1] c
[p-2] TwitterMessage{...}
[single-1] d
...

1 个答案:

答案 0 :(得分:0)

背压发生在大于4个元素的“批次”中。如果您修改生成器以生成更多用户名,例如

  private Consumer<FluxSink<String>> twitterUsernameGenerator() {
        return (sink) -> IntStream.rangeClosed(0, 100000)
                .boxed().map(String::valueOf)
                .collect(Collectors.toList())
                .forEach(sink::next);
    }

产生的通量的行为与预期的相似。

您可以在原始Flux中添加onBackpressureError()

Flux.create(twitterUsernameGenerator())
        .onBackpressureError()
        .publishOn(Schedulers.single())
        .....

通过抛出异常可以清楚地表明何时发生背压。