Spring Cache发生了一些奇怪的事情;也许有人能帮我知道该找什么。
我有两个Spring Boot应用程序:1)“web应用程序”,使用带有Thymelaf的Spring MVC;2)与数据库对话的“后端服务”。后端服务向web应用程序公开了一个RESTful接口,该接口在Thymelaf处理过程中调用(而不是使用Ajax从页面异步调用)。
Thymeleaf -> web app -> (REST over HTTP) -> backend service -> database
我将Spring Cache与
Caffeine
具有
Coffee Boots
以允许我在每个缓存的基础上配置驱逐。以下是Maven POM的一部分:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
<dependency>
<groupId>io.github.stepio.coffee-boots</groupId>
<artifactId>coffee-boots</artifactId>
</dependency>
我使用
@EnableCaching
要在我的web应用程序配置中打开缓存:
@Configuration
@EnableCaching
public class WebAppConfiguration {
â¦
我的web应用程序有
WebAppFooBarRepositoryImpl.getFooBars()
,在启用缓存的情况下:
@Repository("fooBarRepository")
public class WebAppFooBarRepositoryImpl implements WebAppFooBarRepository {
â¦
@Override
@Cacheable("foobar")
public Flux<FooBar> getFooBars() {
System.out.println("CACHE MISS");
return webClient.get().uri("backend-service").â¦
}
â¦
请注意,此存储库方法记录
CACHE MISS
每次调用它时,它都会向后端发出请求。
还请注意,我命名了存储库
fooBarRepository
,以便在Thymelaf中,我可以迭代
Flux<FooBar>
网页中的类似项目:
<li th:each="foobar: ${@fooBarRepository.getFooBars.toIterable()}">[[${foobar}]]</li>
然后后端服务具有
RestController
接受请求,如下所示(网站存储库将
Iterable
到
Flux
):
@GetMapping(path = "backend-service")
public Iterable<FooBar> getFooBars() throws IOException {
System.out.println("backend getting foobars");
return getBackendFooBarRepository().getFooBars();
}
到目前为止,一切都是标准的、无聊的,缓存是唯一一件稍微与众不同的事情。我在web应用程序中添加此配置
application.yaml
在web层缓存foobar结果,每次缓存15分钟:
coffee-boots:
cache:
spec:
foobar: expireAfterWrite=15m
一切就绪后,我加载网页并点击
F5
一次又一次地不断地重新装载。
-
我明白了
缓存未命中
在网站日志中,每15分钟一次。这是意料之中的:web层应该缓存对
WebAppFooBarRepositoryImpl.getFooBars()
,并且只有当缓存超过15分钟时才实际进行调用。
-
然而,每次重新加载页面时,我都会看到“后台获取foobar”,每次点击都会一秒钟多次
F5
!!
这一定意味着
某物
每次重新加载页面时都调用后端服务。但是怎么做呢?通往后端服务的唯一途径是通过
WebAppFooBarRepositoryImpl.getFooBars()
,进行REST调用。如果
WebAppFooBarRepositoryImpl.getFooBars()
如果调用频率更高,则web应用程序将打印
缓存未命中
更频繁地添加到日志中。但该网站正在登录
缓存未命中
每15分钟一次,正如我所期望的那样,无论我多久重新加载一次页面。
记住Spring可能正在为我的
WebAppFooBarRepositoryImpl
例如,我认为拦截调用的缓存逻辑可能会跳过日志输出,但仍然调用后端。但我从未听说过Spring代理解析代码
在…内
方法,并且只跳过其中的一部分;这毫无意义。
目前我无法解释这种奇怪的行为。如果有人有想法,请告诉我。我希望很快它会出现在我的脑海中,我会说,“啊,我不小心做了这样那样的事”,但目前,我真的无法解释这一点。