본문 바로가기
개발/SpringBoot

SpringBoot EhCache JavaConfig설정

by 궁즉변 변즉통 통즉구 2022. 1. 11.
반응형

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

https://idkbj.tistory.com/92

 

반응형

댓글