반응형
1. pom.xml 설정
<!-- cache -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.10.6</version>
</dependency>
2. Cache Config 설정
@EnableCaching
@Configuration
public class CacheConfig {
@Bean
public EhCacheCacheManager ehCacheCacheManager() {
net.sf.ehcache.config.Configuration configuration = new net.sf.ehcache.config.Configuration();
// path는 DiskStoreConfiguration 클래스의 ENV enum 참조하거나 PhysicalPath로 설정
configuration.diskStore(new DiskStoreConfiguration().path("java.io.tmpdir"));
net.sf.ehcache.CacheManager manager = net.sf.ehcache.CacheManager.create(configuration);
CacheConfiguration getCacheConfig = new CacheConfiguration()
.maxEntriesLocalHeap(1000)
.maxEntriesLocalDisk(10000)
.eternal(false)
.timeToIdleSeconds(1800)
.timeToLiveSeconds(1800)
.memoryStoreEvictionPolicy("LRU")
.transactionalMode(TransactionalMode.OFF)
.persistence(new PersistenceConfiguration().strategy(PersistenceConfiguration.Strategy.LOCALTEMPSWAP))
.name("getCache");
Cache getAuthenticatedMenuByUriCache = new Cache(getCacheConfig);
// 캐시 추가
manager.addCache(getAuthenticatedMenuByUriCache);
return new EhCacheCacheManager(manager);
}
* CacheConfiguration 설정 속성
- maxEntriesLocalHeap
- 메모리에 생성될 객체의 최대 수(0: 제한없음) - maxEntriesLocalDisk
- 디스크(DiskStore)에 저장될 객체의 최대 수(0: 제한없음) - eternal
- 저장된 캐시를 제거할지 여부를 설정,
true 인 경우 저장된 캐시는 제거되지 않으며 timeToIdleSeconds, timeToLiveSeconds 설정은 무시 - timeToIdleSeconds
- 생성후 해당 시간 동안 캐쉬가 사용되지 않으면 삭제. 0은 삭제되지 않음. eternal=false 인 경우에만 유효 - timeToLiveSeconds
- 생성후 해당 시간이 지나면 캐쉬는 삭제. 0은 삭제되지 않음. eternal=false 인 경우에만 유효 - diskSpoolBufferSizeMB
- 디스크 캐시에 쓰기 모드로 들어갈때, 사용될 비동기 모드의 스폴 버퍼 크기 설정.
(OutOfMemory 에러가 발생 시 설정한 크기를 낮추는 것이 좋다) - memoryStoreEvictionPolicy
- maxEntriesLocalHeap 설정 값에 도달했을때 설정된 정책에 따리 객체가 제거되고 새로 추가
- LRU(가장 오랫동안 참조되지 않은 것부터 제거), FIFO(먼저 입력된 것부터 제), LFU(가장 적은 참조 횟수부터 제거) - transactionalMode
- copyOnRead, copyOnWrite 시 트랜잭션 모드를 설정
(copyOnRead, copyOnWrite 는 캐시로 받아온 객체에 수정이 일어나는 경우에 사용
-> 캐시된 객체에 수정이 일어나면 참조호출로 인하여 그 뒤에 호출되는 모든 객체가 수정영향이 중첩되어 발생하므로 주의 필요) - persistence
- diskStore 사용 설정("localTempSwap": Temp DiskStore 사용, "none": Only Memory 사용)
3. 테스트
테스트용 Service, Controller 작성
Service작성 시 @Cacheable 작성(CacheConfig의 cache 이름과 동일한 이름으로 설정)
@Cacheable의 "key" 설정으로 param매개변수에 저장된 값을 기준(key)으로 Cache 동작
테스트 호출 예를 들어 "http://localhost:8080/cache/2" 호출 시 최초 호출할 경우 Service 메소드의 log가 출력
두번째 호출부터는 Cache가 적용되어 Service메소드 내부가 실행되지 않고(log 안찍힘) 동일한 리턴값만 확인 가능
4. Cache RMI Cluster 적용
위의 CacheConfig에 Cluster 설정 추가
@EnableCaching
@Configuration
public class CacheConfig {
@Bean
public EhCacheCacheManager ehCacheCacheManager() {
net.sf.ehcache.config.Configuration configuration = new net.sf.ehcache.config.Configuration();
// path는 DiskStoreConfiguration 클래스의 ENV enum 참조하거나 PhysicalPath로 설정
configuration.diskStore(new DiskStoreConfiguration().path("java.io.tmpdir"));
/** Cluster 설정 */
// 노드(피어) 자동 발견 Multicast 설정
FactoryConfiguration factoryConfig = new FactoryConfiguration()
.className("net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory")
.properties("peerDiscovery=automatic,multicastGroupAddress=230.0.0.1,multicastGroupPort=44464,timeToLive=32")
.propertySeparator(",");
// 클러스터에 있는 다른 노드에서 발생한 메시지 수신 리스너 설정
String hostname = System.getProperty("java.rmi.server.hostname"); // [-Djava.rmi.server.hostname=서버자신IP] 설정 필요
FactoryConfiguration listenerFactoryConfig = new FactoryConfiguration()
.className("net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory")
.properties("hostName="+ hostname + ",socketTimeoutMillis=2000") // 방화벽등 port 지정이 필요한 경우 설정 추가(ex. port=12345)
.propertySeparator(",");
configuration.addCacheManagerPeerProviderFactory(factoryConfig);
configuration.addCacheManagerPeerListenerFactory(listenerFactoryConfig);
MulticastKeepaliveHeartbeatSender.setHeartBeatInterval(30000);
net.sf.ehcache.CacheManager manager = net.sf.ehcache.CacheManager.create(configuration);
// 캐시 변경 내역 전송 설정
CacheEventListenerFactoryConfiguration eventListenerFactoryConfig = new CacheEventListenerFactoryConfiguration()
.className("net.sf.ehcache.distribution.RMICacheReplicatorFactory")
.properties("replicateAsynchronously=true,replicatePuts=false,replicateUpdates=true,replicateUpdatesViaCopy=false,replicateRemovals=true")
.propertySeparator(",");
CacheConfiguration getCacheConfig = new CacheConfiguration()
.maxEntriesLocalHeap(1000)
.maxEntriesLocalDisk(10000)
.eternal(false)
.timeToIdleSeconds(1800)
.timeToLiveSeconds(1800)
.memoryStoreEvictionPolicy("LRU")
.transactionalMode(TransactionalMode.OFF)
.persistence(new PersistenceConfiguration().strategy(PersistenceConfiguration.Strategy.LOCALTEMPSWAP))
.name("getCache");
// cacheEventListenerFactory 설정
getCacheConfig = getCacheConfig.cacheEventListenerFactory(eventListenerFactoryConfig);
Cache getAuthenticatedMenuByUriCache = new Cache(getCacheConfig);
// 캐시 추가
manager.addCache(getAuthenticatedMenuByUriCache);
return new EhCacheCacheManager(manager);
}
* CacheEventListenerFactoryConfiguration properties 참조
- replicatePuts: 캐시에 새로운 요소가 추가됐을 때 다른 노드에 복사할지의 여부(기본값 true)
- replicateUpdates: 캐시 요소의 값이 변경되었을 때 다른 노드에 값을 복사할지의 여부(기본값 true)
- replicateRemovals: 캐시 요소가 삭제되었을 때 다른 노드에 반영할지의 여부(기본값 true)
- replicateAsynchronously: 비동기로 값을 복사할지의 여부(기본값 true)
- replicateUpdatesViaCopy: 새로운 요소를 다른 노드에 복사할지 아니면 삭제 메시지를 보낼지의 여부(기본값 true)
- asynchronousReplicationIntervalMillis: 비동기 방식을 사용할 때 변경 내역을 다른 노드에 통지하는 주기. 기본값은 1000.
EHCache RMI Replication 의 단점은 AWS 환경에서 Automatic Peer 기능을 사용할수 없다는것과
Manual Peer 설정은 서버수*캐시수 만큼 설정해야한다고 한다.
참조:
https://oingdaddy.tistory.com/384
반응형
'개발 > SpringBoot' 카테고리의 다른 글
SpringBoot WebConfig @EnableWebMvc, WebMvcConfigurer (0) | 2022.01.19 |
---|---|
SpringBoot static resource 설정 (0) | 2022.01.19 |
addViewControllers()로 불필요 Controller 로직 제거 (0) | 2022.01.10 |
SpringBoot Multi Servlet 추가 MVC설정 분리 테스트 (0) | 2022.01.04 |
SpringBoot 설정에 따른 동적 빈 생성 (0) | 2021.12.09 |
댓글