gpt4 book ai didi

java - 缓存和使缓存的 Mono 失效

转载 作者:行者123 更新时间:2023-12-02 01:14:38 29 4
gpt4 key购买 nike

我在尝试缓存 WebClient 返回的 Mono 时遇到问题。代码是这样的:

public Mono<Token> authenticate() {
return cachedTokenMono = cachedTokenMono
.switchIfEmpty(
Mono.defer(() ->
getToken())
.cache(token ->
Duration.between(Instant.now(), token.getExpires().toInstant()),
(Throwable throwable) -> Duration.ZERO,
() -> Duration.ZERO));
}

目的是缓存用于接收 token Mono,直到 token 过期。 token 过期后,缓存的 Mono 变空,并请求新的 token 。这按预期工作,但不幸的是 switchIfEmpty() 实际上并没有“切换”,而是包装了源代码 Mono。结果,随着创建越来越多的包装 SwitchIfEmptyMono,这会造成内存泄漏。在这种情况下,正确的模式是什么?有没有办法用新的 Mono 替换空的?

最佳答案

你可以这样做:

private final Mono<Token> authenticateMono = getToken()
.cache(
token -> Duration.between(Instant.now(), token.getExpires().toInstant()),
throwable -> Duration.ZERO,
() -> Duration.ZERO)

public Mono<Token> authenticate() {
return authenticateMono;
}

这个想法是您返回相同的缓存 Mono<Token>每次调用 authenticate() 的实例。 .cache运算符确保为每个订阅检查缓存的结果。

具体:

  • 如果有新的订阅到达并且没有缓存值,那么缓存操作符将订阅 Mono<Token>getToken() 返回(这将触发 token 检索)。
  • 如果某个值已被缓存,并且新的订阅在缓存超时之前到达,则缓存运算符会将缓存的值发送给新订阅者
  • 如果某个值已被缓存,并且在缓存超时后有新订阅到达,则缓存运算符将重新订阅 Mono<Token>getToken() 返回(这将触发 token 重新检索)。
  • 如果 Mono<Token>getToken() 返回完成时出现异常,那么该异常将不会被缓存,因此会传播,并且到达的下一个订阅将再次重新触发 token 检索

这一切都假设:

  • getToken()在订阅者到达之前不执行任何操作
  • getToken()检索每个订阅者的 token
  • 您只想为所有订阅者提供一个有效 token

另请注意,根据您的使用案例,您可能希望在 token 到期日期之前稍微使 token 过期,以解决时钟偏差。即在新 token 实际过期之前抢先检索它,以防止返回 Token在下游有机会使用它之前就会过期。

关于java - 缓存和使缓存的 Mono 失效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58867228/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com