Reactor Flux和异步处理

时间:2018-01-25 03:40:18

标签: project-reactor reactor

我正在努力学习Reactor,但我遇到了很多麻烦。我想做一个非常简单的概念证明,我模拟调用慢速下行服务1次或更多次。如果您使用reactor并对响应进行流式处理,则调用者不必等待所有结果。

所以我创建了一个非常简单的控制器,但它的行为并不像我期望的那样。当延迟是"内部"我的flatMap(在我调用的方法内)在一切都完成之前不会返回响应。但是当我在flatMap之后添加延迟时,数据将被流式传输。

为什么此代码会产生JSON流

@GetMapping(value = "/test", produces = { MediaType.APPLICATION_STREAM_JSON_VALUE })
Flux<HashMap<String, Object>> customerCards(@PathVariable String customerId) {
    Integer count = service.getCount(customerId);

    return Flux.range(1, count).
            flatMap(k -> service.doRestCall(k)).delayElements(Duration.ofMillis(5000));

}

但这不是

@GetMapping(value = "/test2", produces = { MediaType.APPLICATION_STREAM_JSON_VALUE })
Flux<HashMap<String, Object>> customerCards(@PathVariable String customerId) {
    Integer count = service.getCount(customerId);

    return Flux.range(1, count).
            flatMap(k -> service.doRestCallWithDelay(k));

}

它认为我遗漏了一些非常基本的反应堆API。在那个说明。任何人都可以指出关于反应堆的好书或教程吗?我似乎找不到任何好的东西来学习这个。

由于

2 个答案:

答案 0 :(得分:0)

这是项目反应堆reference guide “delayElements”方法仅将磁通元素延迟给定的持续时间,请参阅javadoc for more details 我想如果你需要更多的帮助,你应该发布关于方法“service.doRestCallWithDelay(k)”和“service.doRestCall(k)”的详细信息。

答案 1 :(得分:0)

flatMap中的代码在主线程(即控制器运行的线程)上运行。结果,整个过程被阻塞,该方法不会立即返回。请记住,Reactor不会强加特定的线程模型。

相反,根据文档,在delayElements方法signals are delayed and continue on the parallel default Scheduler中。这意味着主线程不会被阻塞并立即返回。

以下是两个相应的示例:

隆重的代码:

Flux.range(1, 500)
    .map(i -> {
            //blocking code
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " - Item : " + i);
            return i;
    })
   .subscribe();
    
    System.out.println("main completed");

结果:

main - Item : 1
main - Item : 2
main - Item : 3
...
main - Item : 500
main completed

非阻塞代码:

Flux.range(1, 500)
    .delayElements(Duration.ofSeconds(1))
    .subscribe(i -> {
        System.out.println(Thread.currentThread().getName() + " - Item : " + i);
    });
    
System.out.println("main Completed");
    
//sleep main thread in order to be able to print the println of the flux
try {
    Thread.sleep(30000);
} catch (InterruptedException e) {
    e.printStackTrace();
}

结果:

main Completed
parallel-1 - Item : 1
parallel-2 - Item : 2
parallel-3 - Item : 3
parallel-4 - Item : 4
...