Spring 3.1과 ehcache

현재 프로젝트는 Spring 3.0.5에 iBatis 캐쉬를 켜서 쓰고 있다.누구도 iBatis에 내장 되어 있는 캐쉬 모델은 추천을 하지도 않고, 게다가 개발PC에서 올리고 한참후 지나면 vm이 멈추는 기현상이 발생이 되긴 하지만, 운영서버와, 개발서버는 아무 이상이 없다. 맥이 잠자기 모드에 들어갈때 먼가 문제가 생기는 모양이다. 여하튼 보이지 않는 위협이 도사리고 있다는 말씀.

ibatis에서만 쓸수 있는 케쉬이기도 하고, 이것은 화면 캐쉬도 할수 있고 전방위적으로 쓸 수 있는 ehcache를 서보기로 했다. 어차피 부하가 걸린 서버도 아니고, 반복적인 DB호출이 있는 부분만 살짝 짧게 캐쉬를 줄예정이다.

참고 자료 : 스프링 3.1 Cache Abstraction

pom.xml

<pre>......
        <spring-version>3.1.0.RELEASE</spring-version>
......
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache-core</artifactId>
            <version>2.5.0</version>
        </dependency>
.......

maven설정에서 spring 3.1.0으로 올리고 ehcahce-core를 추가했다. ehcache를 추가하면 Terracotta캐쉬 서버까지 같이 딸려온다. READ만 하는 경우면 OK라서 core만 가져왔다.

applicationContext-cache.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cache="http://www.springframework.org/schema/cache"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
      http://www.springframework.org/schema/cache >

    <cache:annotation-driven cache-manager="cacheManager" />
    <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
        <property name="cacheManager">
            <bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
                <property name="configLocation" value="classpath:ehcache.xml"></property>
            </bean>
        </property>
    </bean>
</beans>

spring 3.1에서 cache추상화를 시켜서 ehcache만 bean으로 등록하면 된다.

ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd" updateCheck="false">
    <diskStore path="java.io.tmpdir" />

    <defaultCache
        maxElementsInMemory="50000"
        eternal="false"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600"
        overflowToDisk="false"
        diskPersistent="false"
        diskExpiryThreadIntervalSeconds="120"
        memoryStoreEvictionPolicy="LRU">
    </defaultCache>
    <cache name="storedEmp"
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="0"
        timeToLiveSeconds="600"
        overflowToDisk="false"
        diskPersistent="false"
        diskExpiryThreadIntervalSeconds="120"
        memoryStoreEvictionPolicy="LRU">
    </cache>
    <cache name="involvedAccessGroup"
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="0"
        timeToLiveSeconds="60"
        overflowToDisk="false"
        diskPersistent="false"
        diskExpiryThreadIntervalSeconds="120"
        memoryStoreEvictionPolicy="LRU">
    </cache>
</ehcache>

용어 설명
timeToIdleSeconds 몇초간 유휴상태가 지나면 캐쉬를 갱신한다. 0이면 사용하지 않음
timeToLiveSeconds 설정한 초까지 캐쉬를 살린다. 0이면 무한!

캐쉬를 디스크에 쓰지 않으려고 overflowToDisk와 diskPersistent는 꺼버렸다.
그리 많은 캐쉬가 필요한 시스템이 아님.

......
    <import resource="applicationContext-cache.xml" />
......

마지막으로 applicationContext에 import!

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMapConfig PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
        "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
    <settings useStatementNamespaces="true" cacheModelsEnabled="false" classInfoCacheEnabled="false"/>
......

기존 ibatis캐쉬는 쓰지 않는다.

이제 @Cacheable, @CacheEvict를 이용해 키쉬를 설정하면 된다.

......
    @Transactional(readOnly = true)
    @Cacheable(value="storedEmp")
    public Emp getEmpBy(String empNo) {
        Emp paramEmp = new Emp();
        paramEmp.setEmpNo(empNo);
        return empRepository.getEmpBy(paramEmp);
    }

    @Transactional(readOnly = true)
    @Cacheable(value="involvedAccessGroup")
    public boolean isInvolvedAccessGroup(String empNo) {
        boolean involvedAccessGroup = empRepository.isInvolvedAccessGroup(empNo);

        if (!involvedAccessGroup) {
            Emp paramEmp = new Emp();
            paramEmp.setEmpNo(empNo);
            Emp emp = empRepository.getEmpBy(paramEmp);

            List<String> exceptionAccessGroup = empRepository.getExceptionAccessGroup();
            involvedAccessGroup = exceptionAccessGroup.contains(emp.getDeptCd());
        }
        return involvedAccessGroup;
    }
......

@Cacheable에서 value값은 ehcache의 cache이름이다. ibatis캐쉬에서는 캐쉬모델을 하나만 잡아두면 여려종류의 select에서 쓸수 있었지만, 이건 cache마다 큰 Map이라고 보면 된다. storedEmp를 다른곳에서 쓰게 된다면 parameter key마다 같은 캐쉬결과를 리턴한다.

Spring 3.1과 ehcache”에 대한 4개의 생각

댓글 남기기