弹簧通量缓存项目如何管理

时间:2018-09-04 17:47:47

标签: java spring spring-webflux project-reactor

考虑代码示例:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

import java.time.Duration;

import static com.google.common.collect.ImmutableMap.of;

@Component
public class Scratch {

    @Autowired
    private WebClient webClient;

    public Mono<MyClass> getMyClass(Long id) {
        return webClient.get()
                .uri("{id}", of("id", id))
                .retrieve()
                .bodyToMono(MyClass.class)
                .cache(Duration.ofHours(1));
    }
}

规范tells

  

将保留无限制的历史记录,但会应用每个项目的过期超时

什么是项目,什么是缓存的?

  1. 整个http呼叫被缓存。例如。如果我用.get().uri()调用方法链id = 1,那么任何后续调用都会被缓存吗?或
  2. 仅缓存Mono<MyClass>。例如。随后对Mono.map的任何调用都会使用缓存的值吗?

在这两种情况下,什么被视为项目?

1 个答案:

答案 0 :(得分:1)

Reactor中的cache运算符与组件方法上的@Cacheable注释类似。

例如,@Cacheable注释将:

  • 拦截方法调用并根据方法参数计算缓存键
  • 调用该方法并将结果存储在外部缓存中
  • 只要其他人使用相同的参数调用该方法,就提供缓存的结果

所有Reactor运算符都是修饰符,它们返回Flux / Mono-this is why you need to chain operators的新实例。

让我们举个例子:

Scratch scratch = //...
Mono<MyClass> myClass = scratch.getMyClass(12L);

这意味着每当某项订阅特定的Mono实例(而不是scratch.getMyClass(44L);或其他scratch.getMyClass(12L);调用返回的任何其他实例)时,Reactor都会在以下情况下返回缓存的元素:它是第一次被消耗掉的。

当Reactor谈论元素时,它们就是MyClass消息的实例;因为这里是在bodyToMono之后添加了缓存运算符。如果您要将该运算符添加到管道中的其他位置,那就大不一样了,也就是说,它将缓存另一件事。

现在,该功能不能为所有类似的HTTP调用实现HTTP客户端缓存。如果您的应用程序的多个部分需要完全相同的数据,并且您不想浪费资源一遍又一遍地获取相同的内容,则此功能很有用。

例如,假设此HTTP调用很昂贵,并且您想在多个地方使用该MyClass实例:

Mono<MyClass> myClass = scratch.getMyClass(12L);
Mono<Void> result = saveToDatabase(myClass).then(calculateStats(myClass));

另一种用例是,当您想将数据流共享给多个客户端时:

@RestController
public class StreamingController {

    private Flux<StockQuotes> quotes = quoteService.fetch().cache(Duration.ofSeconds(5));

    @GetMapping("/quotes")
    public Flux<StockQuotes> streamQuotes() {
        return this.quotes;
    }

在这种情况下,每次新的HTTP客户端请求服务器并从中传输数据时,服务器都不会创建与远程库存服务的新连接,而是会重播最近5秒钟的报价(然后其余部分继续操作)