programing

Spring Webflux 및 @Cacheable - 모노/플럭스 유형의 올바른 결과 캐싱 방법

fastcode 2023. 3. 21. 22:38
반응형

Spring Webflux 및 @Cacheable - 모노/플럭스 유형의 올바른 결과 캐싱 방법

저는 Spring WebFlux를 배우고 있는데 샘플 어플리케이션을 작성하는 동안 Spring Cache와 결합된 Reactive type(Mono/Flux)과 관련된 문제를 발견했습니다.

다음 코드 스니펫(Kotlin의 경우)을 검토합니다.

@Repository
interface TaskRepository : ReactiveMongoRepository<Task, String>

@Service
class TaskService(val taskRepository: TaskRepository) {

    @Cacheable("tasks")
    fun get(id: String): Mono<Task> = taskRepository.findById(id)
}

이것이 Mono 또는 Flux를 반환하는 메서드 콜을 캐싱하는 유효하고 안전한 방법입니까?다른 원칙이 있을까요?

다음 코드는 SimpleCacheResolver에서 작동하지만 Mono는 직렬화할 수 없기 때문에 Redis에서 기본적으로 실패합니다.작동시키려면 예를 들어 Kryo 시리얼라이저를 사용해야 합니다.

해킹 방법

현시점에서는, 의 원활한 통합은 행해지지 않고 있습니다.@Cacheable리액터 3에 접속합니다.단, 다음을 추가하여 해당 항목을 우회할 수 있습니다..cache()반환할 연산자Mono

@Repository
interface TaskRepository : ReactiveMongoRepository<Task, String>

@Service
class TaskService(val taskRepository: TaskRepository) {

    @Cacheable("tasks")
    fun get(id: String): Mono<Task> = taskRepository.findById(id).cache()
}

해킹 캐시와 공유가taskRepository다시, 스프링 캐시 가능은 반환된 참조를 캐시합니다.Mono그런 다음 해당 참조를 반환합니다.즉, 이것은 캐시를 유지하는 모노의 캐시입니다.

Reactor Addons 웨이

Reactor 3에는 카페인, jcache 등의 최신 인메모리 캐시와의 원활한 통합을 가능하게 하는 추가 기능이 있습니다.이 기술을 사용하면 데이터를 쉽게 캐시할 수 있습니다.

@Repository
interface TaskRepository : ReactiveMongoRepository<Task, String>

@Service
class TaskService(val taskRepository: TaskRepository) {

    @Autowire
    CacheManager manager;


    fun get(id: String): Mono<Task> = CacheMono.lookup(reader(), id)
                                               .onCacheMissResume(() -> taskRepository.findById(id))
                                               .andWriteWith(writer());

    fun reader(): CacheMono.MonoCacheReader<String, Task> = key -> Mono.<Signal<Task>>justOrEmpty((Signal) manager.getCache("tasks").get(key).get())
    fun writer(): CacheMono.MonoCacheWriter<String, Task> = (key, value) -> Mono.fromRunnable(() -> manager.getCache("tasks").put(key, value));
} 

주의: Reactor Addon은 자체 추상화를 캐시합니다.Signal<T>그러니 걱정하지 말고 그 규칙을 따르세요.

올레 도쿠카의 해킹 솔루션이 잘 먹혔지만 단서가 하나 있어요.Creachable 캐시 timolive 값보다 더 큰 Duration in Flux 캐시를 사용해야 합니다.플럭스 캐시에 기간을 사용하지 않으면 무효화되지 않습니다(플럭스 문서에는 "이 플럭스를 핫 소스로 전환하고 추가 서브스크라이버를 위해 마지막으로 내보낸 신호를 캐시하십시오."라고 기재되어 있습니다).따라서 Flux 캐시를 2분 30초 단위로 설정하는 것이 유효한 구성이 될 수 있습니다.ehcahce 타임아웃이 먼저 발생하면 새로운 플럭스 캐시 참조가 생성되어 사용됩니다.

// 전면:

public Mono<HybrisResponse> getProducts(HybrisRequest request) {
    return Mono.just(HybrisResponse.builder().build());
}

// 서비스 레이어:

@Cacheable(cacheNames = "embarkations")
public HybrisResponse cacheable(HybrisRequest request) {
    LOGGER.info("executing cacheable");
    return null;
}

@CachePut(cacheNames = "embarkations")
public HybrisResponse cachePut(HybrisRequest request) {
    LOGGER.info("executing cachePut");
    return hybrisFacade.getProducts(request).block();
}

// 컨트롤러 내:

HybrisResponse hybrisResponse = null;

try {
   // get from cache
   hybrisResponse = productFeederService.cacheable(request);

} catch (Throwable e) {
   // if not in cache then cache it
   hybrisResponse = productFeederService.cachePut(request);
}

return Mono.just(hybrisResponse)
    .map(result -> ResponseBody.<HybrisResponse>builder()
        .payload(result).build())
    .map(ResponseEntity::ok);

언급URL : https://stackoverflow.com/questions/48156424/spring-webflux-and-cacheable-proper-way-of-caching-result-of-mono-flux-type

반응형