【问题标题】:How is spring flux cache item managedspringflux缓存项如何管理
【发布时间】:2019-02-09 19:11:11
【问题描述】:

考虑代码示例:

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

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

什么是item,什么是缓存?

  1. 整个 http 调用被缓存。例如。如果我用id = 1 调用方法链.get().uri(),任何后续调用都会被缓存?或
  2. 仅缓存Mono&lt;MyClass&gt;。例如。对Mono.map 的任何后续调用都将使用缓存值?

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

【问题讨论】:

    标签: java spring spring-webflux project-reactor


    【解决方案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 秒的报价(然后继续其余的)所有新订阅。

    【讨论】:

      猜你喜欢
      • 2011-07-16
      • 2014-04-15
      • 1970-01-01
      • 1970-01-01
      • 2017-01-24
      • 2021-12-07
      • 1970-01-01
      • 2015-01-15
      • 2016-11-23
      相关资源
      最近更新 更多