아래 포스팅에서 이어진다.
https://123okk2.tistory.com/326
기본적으로 아무런 선언 없이 캐시를 사용하면 ConcurrentMapCacheManager가 빈으로 등록되어 사용된다.
@Autowired CacheManager cacheManager;
public String getCacheType() {
return cacheManager.toString();
}
프로젝트를 만들어 위의 함수를 만든 다음 테스트로 함수를 실행시켜보면 아래의 결과를 얻을 수 있다.
그런데 참여중이거나 참여 예정인 프로젝트들을 보면, 대부분의 경우 위처럼 별도의 설정을 하지 않은 캐시가 아닌, 별도의 설정을 통하여 ehcache를 사용하고 있음을 발견했다.
Ehcache는 대규모의 동시성 시스템을 위해 설계되어 빠르고 단순하며, 앱을 최대한 가볍게 유지하여 작은 공간을 유지한다. 또한 최소한의 종속성만을 가지는 장점이 있다고 한다.
위의 내용은 아래의 링크에서 확인 가능하다.
https://www.ehcache.org/about/features
어쨌든 현재 재직중인 회사에서 캐시를 사용할 때 ehcache를 자주 사용한다는 것을 알았고, 당장은 모든 프로젝트에서 다른 시니어 개발자분들께서 이미 ehcache 세팅을 완료해놓으신 상태이지만 언제 어떤 프로젝트에서 내가 세팅을 하게 될 지 모르니 한 번 정도는 간단하게라도 사용법을 공부하면 좋을 것 같다는 생각이 들었다.
ehcache의 사용법은 xml을 만들어 몇 가지 설정사항들을 적용해놓고 Configuration클래스 파일을 만들어 CacheManager 빈에 EhCacheCacheManager 클래스를 매핑시키고, 해당 매니저가 방금 언급한 xml의 설정을 가지게 만들면 된다.
가장 먼저 pom.xml에 다음 dependency를 추가한다.
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.6.10</version>
</dependency>
그 후에는 xml파일을 먼저 설정하자. 방법은 아래와 같다.
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true"
monitoring="autodetect" dynamicConfig="true">
<diskStore path="java.io.tmpdir"/>
<defaultCache
maxEntriesLocalHeap="10000"
maxEntriesLocalDisk="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"/>
<cache name="testCache"
maxElementsInMemory="10"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU">
<persistence strategy="localTempSwap" />
</cache>
</ehcache>
큰 틀은 아래와 같다.
- diskStore : 데이터의 임시저장 경로로, 여러 개의 CacheManager 사용 시 여러 경로를 사용하는 것이 좋다.
- sizeOfPolicy : maxDepth(캐시에 저장될 객체 레퍼런스의 최대값), maxDepthExceededBegavior(객체가 maxDepth를 초과할 경우에 사이징 시 정책 : continue/abort : abort는 사이징 중지 후 부분적으로 계산된 크기 반환)
- defaultCache : 가장 기본적인 캐시 설정
- cache : 특정 이름의 캐시들에 대한 설정
그리고 defaultCache와 cache에는 캐시의 설정이 들어가게 되는데, 설정 가능 항목은 아래와 같이 구성된다.
변수명 | 설명 | default |
maxEntriesLocalHeap | 힙 메모리에 생성될 최대 캐시수 | 0 |
maxMemoryOffHeap | 캐시 메모리에 생성될 최대 캐시 수. GC 개상이 된다. | |
maxEntriesLocalDisk | 디스크에 생성될 최대 캐시수. ehcache가 관리하며 GC대상에서 제외된다. |
0 |
eternal | 영속성 캐시 설정 즉 true이면 timeTodleSecond, timeToLiveSeconds가 무시된다. |
false |
timeToIdleSecond | 해당 단위시간(초)동안 캐시 미호출시 삭제 | 0 |
timeToLiveSeconds | 해당 초가 지나면 캐시 삭게 | 0 |
overflowToDisk | 오버플로우된 항목을 disk에 저장할지 여부 | false |
diskPersistent | 캐시를 disk에 저장하여 서버 로드 시 캐시를 가져올지 설정 | false |
diskExpiryStoreEvictionPolicy | Disk Expiry 스레드의 작업 수행 시간 간격 | 0 |
memoryStoreEvictionPolicy | 캐시의 객치 수가 maxEntriesLocalHeap에 도달 시 객체를 추가하고 제거하는 정책 (LRU, LFU, FIFO) | LRU |
그리고 ehcache를 사용할 Configuration은 다음과 같이 구성한다.
package com.example.demo;
import org.springframework.cache.CacheManager;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
@Configuration
public class CacheConfig {
@Bean
public EhCacheManagerFactoryBean ehCacheCacheManager() {
EhCacheManagerFactoryBean cmfb = new EhCacheManagerFactoryBean();
cmfb.setConfigLocation(new ClassPathResource("ehcache.xml"));
cmfb.setShared(true);
return cmfb;
}
@Bean
public CacheManager cacheManager() {
return new EhCacheCacheManager(ehCacheCacheManager().getObject());
}
}
그 후 위에서 만든 테스트를 다시 한 번 돌려보면 이번에는 EhCacheCacheManager가 호출됨을 확인할 수 있다.
그리고 ehcache를 공부하면서 느낀 점은 캐시에 대한 다양한 세팅이 가능하여 Redis를 어느정도 대체할 수 있을 것 같다는 것이다.
가장 메리트가 있는 부분은 아무래도 timeToIdleSecond, timeToLiveSeconds 인 것 같다.
그래서 해당 기능이 잘 동작하는지 확인하기 위해 위의 세팅에서 testCache1, testCache2를 생성하고 각 timeToLiveSeconds를 3초, 1초로 설정해보았다.
<cache name="testCache1"
maxElementsInMemory="10"
eternal="false"
timeToIdleSeconds="3"
timeToLiveSeconds="3"
memoryStoreEvictionPolicy="LRU">
<persistence strategy="localTempSwap" />
</cache>
<cache name="testCache2"
maxElementsInMemory="10"
eternal="false"
timeToIdleSeconds="1"
timeToLiveSeconds="1"
memoryStoreEvictionPolicy="LRU">
<persistence strategy="localTempSwap" />
</cache>
그리고 아래와 같은 함수를 작성하여 테스트를 실행해보았다.
@Cacheable("testCache1")
public String testCache1() {
logger.info("testCache1 INIT");
return "testCache1";
}
@Cacheable("testCache2")
public String testCache2() {
logger.info("testCache2 INIT");
return "testCache2";
}
@Test
void cacheTest() throws InterruptedException {
logger.info(cacheService.testCache1());
logger.info(cacheService.testCache2());
Thread.sleep(2000);
logger.info(cacheService.testCache1());
logger.info(cacheService.testCache2());
}
아래와 같은 결과가 출력되며 testCache2만 시간이 지나 사라져 함수가 재호출됨을 확인할 수 있었다.
'실습 > 리눅스 서버 + 스프링 부트' 카테고리의 다른 글
Spring WebFlux Filter (1) | 2022.07.25 |
---|---|
Spring Security rememberMe (자동 로그인) (0) | 2022.07.25 |
Redis In Java_메시지 큐 (0) | 2022.03.20 |
Redis In Java_자료구조 (0) | 2022.03.20 |
Spring Cloud Config (0) | 2022.03.13 |