You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现具备定时缓存、到期自动重载功能的Mono?适配/jwks端点

解决Reactor缓存JWKS数据的问题

针对你在/jwks端点缓存数据库数据时遇到的问题,以下是具体分析和解决方案:

关于Mono.cache(Duration)的问题

你遇到的“仅执行一次调用,之后返回空值”,核心原因是若首次数据库查询返回的是空Mono(而非包含空集合的Mono),cache(Duration)会缓存这个空信号,直到过期前所有请求都会返回空。

解决方式:

  • 确保数据库查询逻辑返回的是包含实际数据(或空集合)的Mono,而非空Mono。比如查询结果为空时,返回Mono.just(Collections.emptyList())而不是Mono.empty()。
  • 若需要针对空结果设置更短的缓存时长,使用cache的重载方法:
    // 成功结果缓存10分钟,空结果仅缓存1分钟,更快触发重新查询
    mono.cache(Duration.ofMinutes(10), Duration.ofMinutes(1));
    

关于Flux.cache(Duration)的问题

Flux.cache(Duration)默认会缓存所有元素,每次订阅都会重放全部元素。你遇到“仅返回最后一条条目”,大概率是订阅时误用了last()、takeLast(1)这类操作符,或者源Flux本身只发出最后一个元素。

解决方式:

  • 如果需要返回所有JWK元素,直接订阅缓存后的Flux即可,不要额外添加限制只取最后一个的操作符。
  • 更推荐用Mono<List<JWK>>包装整个JWKS集合,这更符合JWKS接口返回单个JSON数组的场景,缓存和序列化也更简单。

推荐的实现方案

以下是生产环境常用的缓存JWKS数据的代码示例:

import reactor.core.publisher.Mono;
import java.time.Duration;
import java.util.Collections;
import java.util.List;
import java.util.Map;

// 数据库查询逻辑,每次调用都会执行实际查询
private Mono<List<JWK>> fetchJwksFromDb() {
    return Mono.fromCallable(() -> {
        // 替换为你的数据库查询代码
        List<JWK> jwks = jwkRepository.findAll();
        // 确保不会返回空Mono,空结果返回空集合
        return jwks != null ? jwks : Collections.emptyList();
    }).subscribeOn(Schedulers.boundedElastic()); // 数据库查询放在IO线程池
}

// 缓存实例:全局单例,确保缓存共享
private final Mono<List<JWK>> cachedJwks = fetchJwksFromDb()
        .cache(
            Duration.ofMinutes(10), // 成功结果缓存10分钟
            Duration.ofMinutes(1),  // 空结果缓存1分钟(可选)
            Duration.ofMinutes(10)  // 错误结果缓存10分钟(可选,根据错误类型调整)
        );

// /jwks端点处理方法
@GetMapping("/jwks")
public Mono<Map<String, List<JWK>>> getJwks() {
    return cachedJwks.map(jwks -> Map.of("keys", jwks));
}

这个方案的优势:

  • 首次请求触发数据库查询,后续请求直接返回缓存,直到10分钟后缓存过期自动刷新。
  • 避免空Mono导致的持续空返回问题。
  • 数据库查询放在IO线程池,不阻塞主线程。

内容的提问来源于stack exchange,提问作者Archimedes Trajano

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 20:54:17