在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