跳到主要内容

在WebFlux中如何使用缓存,缓存Mono和Flux

前言

在传统项目中,使用缓存框架对一个方法的返回做缓存那是再简单不过的事,缓存框架也是有多重选择,比如EHcache,Caffeine,jetcache,Guava Cache等等等。

但是当我真的把webflux应用到真实项目的时候才发现,因为响应式编程中的异步调度,几乎让所有的方法返回都套上了Mono<T>, Flux<T>,似乎之前的缓存框架没有那么简单能融合进项目中。

为此,我收集了常见的缓存框架对project-reactor(webflux中的响应式编程框架)支持,发现并没有我想的这么简单。

如下图:

框架名支持情况相关链接
ehcache不支持Possibility to provide asynchronous or reactive cache in future versions
jetcache不支持jetcache 支持 spring webflux 吗
reactor-extra最新版本已经停止更新reactor-addons
caffeine支持Reactive types support for @Cacheable methods 但是要求是spring 6.1M4版本之后

方法一:使用caffeine + spring @Cacheable

这种方式的集成度最好,而且有spring团队的背书,相信性能和安全性也是有保证的,但是可惜的是,需要spring 6.1 M4之后的版本。

使用方式:

@SpringBootApplication
@Configuration
@EnableCaching
public class MakeSomeToolsApplication {

public static void main(String[] args) {
SpringApplication.run(MakeSomeToolsApplication.class, args);
}

@Bean
public CaffeineCacheManager caffeineCache() {
CaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager();
Caffeine<Object, Object> caffeine = Caffeine.newBuilder()
.expireAfterWrite(60, TimeUnit.MINUTES);
caffeineCacheManager.setCaffeine(caffeine);
caffeineCacheManager.setAsyncCacheMode(true);
return caffeineCacheManager;
}
}
  • 增加@EnableCaching注解
  • 注入bean CaffeineCacheManager,而且要设置setAsyncCacheMode 为true,这是必须的
  • Caffeine.newBuilder() 可以配置你的缓存策略

接着你就可以在方法上使用注解@Cacheable ,原汁原味,很丝滑。缺点是不够定制话,如果你之前有使用过@Cacheable,你就知道,它没法对某个方法的返回值设置过期时间,这些需要自己写代码进行扩展。

方法二:使用AOP实现

这里并不是让你自己写一套AOP拦截方法执行,然后设置缓存策略,而是已经有大佬帮我们写好,我们只需要使用就行。

仓库地址:https://github.com/shaikezr/async-cacheable

把这几个类复制到你的项目中,然后就能在方法上使用@AsyncCacheable

在项目启动的时候,就会自动根据你的配置设置对应缓存策略的,不过目前支持的特性并不多,只有如下三个:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AsyncCacheable {

String name() default "default1000Item5MinuteCache";

long maximumSize() default 1000L;

long expireAfterWriteSeconds() default 300L;

}

好消息是如果你想对其进行扩展并不难,只要你知道一些AOP的知识就能在AsyncCacheableMethodProcessor 中自己扩展,所以caffeine 支持的特性,都能在注解上加上。

这个项目相关的一些内容,如果你想知道的话:

Integration Support with Spring Webflux ?

还有高手!

方法一、二你都不满意,还有解决办法,完全的定制化,完全的自主可控。但是需要你有高深的代码能力了。

caffeine缓存的作者在项目中写了个例子,试图教会我们怎么把project-reactor和caffeine的AsyncCacheLoader完美的结合起来。看了一下感觉既需要对project-reactor非常熟练+对caffeine异步缓存相当了解才能写的比较完美。

链接:https://github.com/ben-manes/caffeine/tree/master/examples/coalescing-bulkloader-reactor