Project Reactor: How to control Flux emission

眉间皱痕 提交于 2021-02-07 10:19:45

问题


I have a flux that emits some Date. This Date is mapped to 1024 simulated HTTP requests that I'm running on some Executer.

What I'd like to do is waiting for all the 1024 HTTP requests before emitting the next Date.

Currently when running, onNext() is called for many times and then it is stabilised on some steady rate.

How can I change this behaviour?

P.S. I'm willing to change to architecture, if needed.

private void run() throws Exception {

    Executor executor = Executors.newFixedThreadPool(2);

    Flux<Date> source = Flux.generate(emitter ->
        emitter.next(new Date())
    );

    source
            .log()
            .limitRate(1)
            .doOnNext(date -> System.out.println("on next: " + date))
            .map(date -> Flux.range(0, 1024))
            .flatMap(i -> Mono.fromCallable(Pipeline::simulateHttp)
                    .subscribeOn(Schedulers.fromExecutor(executor)))
            .subscribe(s -> System.out.println(s));

    Thread.currentThread().join();
}

HTTP request simulation:

private static String simulateHttp() {
    try {
        System.out.println("start http call");
        Thread.sleep(3_000);
    } catch (Exception e) {}

    return "HTML content";
}

EDIT: adapted code from answer:

  • First, I had a bug in my code (another flatMap was needed)
  • Second, I added concurrency parameter of 1 to both flatMap (it seems that both are needed)

    Executor executor = Executors.newSingleThreadExecutor();
    
    Flux<Date> source = Flux.generate(emitter -> {
        System.out.println("emitter called!");
        emitter.next(new Date());
    });
    
    source
            .limitRate(1)
            .map(date -> Flux.range(0, 16))
            .flatMap(Function.identity(), 1) # concurrency = 1
            .flatMap(i -> Mono.fromCallable(Pipeline::simulateHttp)
                    .subscribeOn(Schedulers.fromExecutor(executor)), 1) # concurrency = 1
            .subscribe(s -> System.out.println(s));
    
    Thread.currentThread().join();
    

回答1:


You should take a look at these methods:

  • Flux.flatMap(Function, int, int)
  • Flux.concatMap(Function, int).

concatMap ensures that the elements on the flux are processed sequentially inside the operator:

Generation of inners and subscription: this operator waits for one inner to complete before generating the next one and subscribing to it.

flatMap lets you do the same by exposing concurrency and prefetch parameters which provide you more control over this behavior:

The concurrency argument allows to control how many Publisher can be subscribed to and merged in parallel. In turn, that argument shows the size of the first Subscription.request(long) to the upstream. The prefetch argument allows to give an arbitrary prefetch size to the merged Publisher (in other words prefetch size means the size of the first Subscription.request(long) to the merged Publisher).



来源:https://stackoverflow.com/questions/57199893/project-reactor-how-to-control-flux-emission

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!