참고 - http://linuxism.tistory.com/1265
출처 - http://javacan.tistory.com/123
Ehcache는 가장 표준적인 캐시의 모습을 한 오픈소스 캐시 라이브러리입니다. 얼마전 JCO에 갔을때 보니 이번엔 정말 캐시가 화두인것 같더군요. 하지만 당시에 발표된 대부분의 캐시 시스템은 Memcached, Redis같은 클러스터 기반의 외부형 초대규모 캐시들이었습니다. 이번에 간단하게 쓸 수 있는 캐시 라이브러리가 없을까 검색하다 보니 발견한 ehcache-spring-annotation 라이브러리는 캐시사용을 정말 쉽고 간단하게 만들어 줍니다.
자주 바뀌지 않는 결과물인, 가령 공지사항이라던가 페이지의 첫화면(index)과 같은 경우에 적극적으로 활용할 수 있을것 같습니다. 이번에 쓰는 글은 메이븐 기반의 프로젝트 구성을 할 예정입니다. 지식이 부족하시다면 [관련글]을 좀 더 보시고 오시면 도움이 될것입니다. 스프링 프로젝트의 구성에는 충분히 이해도가 높은 분들이 보시는 글이라 생각하고 그런 부분은 종종 건너 뛰도록 하겠습니다.
Maven 프로젝트 구성
임시로 사용할 프로젝트이니 다음과 같은 정도만 등록해주시면 될것 같습니다. XML을 올릴까 싶었지만 글중에 스크린샷 하나쯤 등장하는게 아름다울것 같아 다음의 스크린샷으로 대신합니다.스프링 프로젝트 컨텍스트 설정에 ehcache 설정 추가
스프링의 컨텍스트 설정 XML에 다음의 코드를 추가해 줍니다. 설정파일이 여러개로 분산되어있다면 어디에 들어가던지 순서는 상관없습니다.<ehcache:annotation-driven />
<ehcache:config cache-manager="cacheManager">
<ehcache:evict-expired-elements interval="300" />
</ehcache:config>
<bean id="cacheManager"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="/WEB-INF/cache/ehcache.xml" />
</bean>
여기서 중요한점은 <beans> 네임스페이스 선언에 다음이 추가되어야 합니다.
xmlns:ehcache="http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring"
xsi:schemaLocation="http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring/ehcache-spring-1.1.xsd"
보기가 어렵지만 달리 방법이 없네요. 결과적으로 다음과 같은 모습이 됩니다.
<?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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:ehcache="http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring/ehcache-spring-1.1.xsd">
<ehcache:annotation-driven />
<ehcache:config cache-manager="cacheManager">
<ehcache:evict-expired-elements interval="300" />
</ehcache:config>
<bean id="cacheManager"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="/WEB-INF/cache/ehcache.xml" />
</bean>
</beans>
Ehcache 설정 파일 생성
이번엔 Ehcache의 설정 파일을 추가해주어야 합니다. 위에서 /WEB-INF/cache/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"
maxBytesLocalHeap="32M" maxBytesLocalOffHeap="128M"
maxBytesLocalDisk="0M" updateCheck="false">
<cache
name="CacheExample"
maxElementsInMemory="100"
eternal="false"
overflowToDisk="false"
timeToLiveSeconds="30" />
</ehcache>
위의 설정을 대충 보자면 CacheExample이라는 이름의 캐시를 생성을 합니다. 한번에 최대 100개의 엘리먼트를 보관(maxElementsInMemory)할 수 있으며 영원히 저장하지 않고(eternal) 특정 상황에서 삭제 되어도 상관없다는 설정이 되어있습니다. 디스크까지 저장하면 캐시의 의미가 퇴색되므로 디스크는 절대로 사용하지 않을것이고(overflowToDisk) 한번 꺼내온 데이터는 30초동안만 유지하겠습니다(timeToLiveSeconds). 30초가 지나면 데이터를 파기합니다.
<ehcache> 선언부에 있는 설정들은 전체 캐시를 총괄하는 글로벌 설정입니다.
DAO 클래스에 캐시 추가하기
다음과 같이 크게 기억해둘 부분은 두가지 입니다. 설정된 캐시 정보대로 값을 캐시하며 실제 내부 로직이 실행될지 캐시가 반환 될지를 결정할 @Cacheable 어노테이션과 캐시 설정과 상관없이 당장 캐시를 삭제하는 @TriggersRemove 어노테이션을 잘 봐두시면 됩니다.@Repository
public class CacheDao
{
@TriggersRemove(cacheName="CacheExample", removeAll=true, when=When.AFTER_METHOD_INVOCATION)
public void insertDummy()
{
// 캐시 삭제 예시를 위해 존재하는 메소드
}
@Cacheable(cacheName="CacheExample")
public String getDummy()
{
// 캐시가 존재할 경우 이 로직은 실행되지 않고 캐시가 바로 반환됩니다.
return new Date().toString();
}
}
테스트용 컨트롤러 제작하기
지금 보여드릴 코드는 순전히 테스트를 위한 코드입니다. 데이터를 가져오는 부분과 데이터를 날리는 부분이 있습니다.@Controller
@RequestMapping("/example")
public class CacheController
{
@Autowired private CacheService cacheService;
@RequestMapping("/main")
public String showIndex(Model model)
{
model.addAttribute("now", cacheService.getDummy());
return "index";
}
@RequestMapping("/flush")
public String flushCache()
{
cacheService.insertDummy();
return "redirect:/example/main";
}
}
showIndex가 실행이 되면 cacheService를 통해 cacheDao를 통해 값을 가져오게 됩니다. 아까 설정했던 캐시 규칙에 의거해 한번 캐시된 데이터는 100개의 데이터를 넘지 않는 이상 30초간 캐시 됩니다. 뷰에서는 꺼내온 데이터를 그대로 찍도록 만들어져 있습니다.
캐싱 테스트 해보기
실행을 해보니깐 현재의 시간이 잘 출력이 됩니다. 하지만 다시한번 재 요청을 해보시면 시간이 변하지 않는것을 확인하실 수 있습니다. 계속 재 요청을 해도 같은 화면이 출력이 되며 30초 뒤에 캐시가 사라졌을법한 뒤에 다시 요청을 해 보시면 다시 DAO의 내부 로직이 실행되어 현재 시간이 출력됩니다.
여기서 flushCache를 실행하게 되면 곧바로 캐시가 삭제되어(실제로는 새로운 데이터가 입력되어 전체 데이터에 변동이 일어나 더이상 기존의 캐시가 유효하지 않게 되었으므로 삭제하는것이겠죠) 더이상 캐시가 유효하지 않게 되고 이후 원래 화면으로 리다이렉트 되면 다시 캐시없는 상태에서 데이터 가져오기가 실행되게 됩니다. 예시로 만들었던 소스를 올려 놓겠습니다.
참고:
http://code.google.com/p/ehcache-spring-annotations/w/list
http://blog.goyello.com/2010/07/29/quick-start-with-ehcache-annotations-for-spring/
출처 - http://theeye.pe.kr/entry/simple-way-of-caching-my-data-access-object-with-spring-annotation
처리 속도 개선을 위해 cache를 적용했다.
시스템간 연동으로 접속부하, 네트웍부하가 동시에 생겨 속도저하가 심각한 화면이 생김!!
문제는 조회조건부 - 회계년도, 부서, 코드관련.....
가져오는 데이터는 거의 동일한데도...
화면이 바뀌거나, 조회콤보 선택처리에 DB까지 데이터 엑세스가 반복적으로 발생.
이 부분에 cache를 적용해볼 생각으로 자료를 찾았더니 가장 많이 선택된 솔루션이 ehcache.....
ehcache를 심도있게 학습하고 적용할 상황은 아니라서
spring에 annotation기반으로 빠르게 적용할 수 있는 방법을 찾음 ehcache-spring-annotations
현재 개발중인 시스템에 적용된 spring버전은 3.0.5.RELEASE이다.
maven을 사용하고 있다면 다음과 같은 dependency추가가 필요하다.
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>3.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>com.googlecode.ehcache-spring-annotations</groupId>
<artifactId>ehcache-spring-annotations</artifactId>
<version>1.1.3</version>
</dependency>
위 2개의 dependency를 추가하면 그와 연결된 관련 dependency까지 setting이 완료된다.
maven의 혜택...ㅋ~~~~
maven에 의해 ehcache관련 필수 라이브러리가 classpath상에 위치하게 되었으므로
설정과 코드수정만 남았다.
먼저 beans.xml 또는 applicationContext.xml 등 spring configuration파일의
네임스페이스 부분에 추가설정이 필요
<?xml version="1.0" encoding="UTF-8"?>
짙게 표시된 부분이 추가한 내용이다.
그리고 동일 설정파일에 아래 코드를 추가한다.
이제 설정 작업은 끝났다.
WEB-INF/ root 디렉토리에 다음과 같은 내용의 ehcache.xml파일을 생성하자.
</dependency>
위 2개의 dependency를 추가하면 그와 연결된 관련 dependency까지 setting이 완료된다.
maven의 혜택...ㅋ~~~~
maven에 의해 ehcache관련 필수 라이브러리가 classpath상에 위치하게 되었으므로
설정과 코드수정만 남았다.
먼저 beans.xml 또는 applicationContext.xml 등 spring configuration파일의
네임스페이스 부분에 추가설정이 필요
<?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:ehcache="http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring
http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring/ehcache-spring-1.1.xsd">
짙게 표시된 부분이 추가한 내용이다.
그리고 동일 설정파일에 아래 코드를 추가한다.
<!-- declare ehCache -->
<ehcache:annotation-driven />
<ehcache:config cache-manager="cacheManager">
<ehcache:evict-expired-elements interval="60" />
</ehcache:config>
<!-- ehCache bean -->
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" >
<property name="configLocation" value="/WEB-INF/ehcache.xml"/>
</bean> 이제 설정 작업은 끝났다.
WEB-INF/ root 디렉토리에 다음과 같은 내용의 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">
<defaultCache
eternal="false"
maxElementsInMemory="1000"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="0"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU"/>
<cache
name="budgetCache"
eternal="false"
maxElementsInMemory="100"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="0"
timeToLiveSeconds="300"
memoryStoreEvictionPolicy="LRU" />
<cache
name="accountCache"
eternal="false"
maxElementsInMemory="100"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="0"
timeToLiveSeconds="300"
memoryStoreEvictionPolicy="LRU" />
</ehcache>
배포파일의 element, 설정값 등은
환경에 맞게 수정해서 사용하면 될 것이다.
지금까지 한 작업을 정리해보면...
1. dependency추가 완료
2. spring configuration 파일(beans.xml 또는 applicationContext.xml 등 설정 파일) 설정 추가 완료
3. ehcache configuration 파일 작성 및 배포준비 완료(WEB-INF)
이제 실제 Java code에 적용하는 일만 남았다...
다음 코드는 @Cacheable annotation을 적용한 소스의 일부이다.
@Cacheable annotation선언만으로 캐시기능은 훌륭하게 작동된다.
실제로 한게 너무 없어 황당할 정도...
서비스 영역의 캐시가 완료되면 client영역에서 최초 조회시 원래 속도로 나오고
반복적인 조회에서는 엄청난(?) 속도향상이 이뤄졌다.
cache적용이 유용한 부분은
코드성 데이터 조회 부분,
기본 데이터이지만 반복적으로 호출되는 부분
출력물의 코드, 부서 매핑이 필요한 부분 등일 것이다..
웹상에 공개된 문서나 자료만을 참고해서 급하게 적용하느라
심도있는 이해나 준비가 부족했다.
추후 보완이 필요한 부분이다.
배포파일의 element, 설정값 등은
환경에 맞게 수정해서 사용하면 될 것이다.
지금까지 한 작업을 정리해보면...
1. dependency추가 완료
2. spring configuration 파일(beans.xml 또는 applicationContext.xml 등 설정 파일) 설정 추가 완료
3. ehcache configuration 파일 작성 및 배포준비 완료(WEB-INF)
이제 실제 Java code에 적용하는 일만 남았다...
다음 코드는 @Cacheable annotation을 적용한 소스의 일부이다.
package pe.tuenas.prototype.soapservice.budget.impl; import .... 생략 @WebService( endpointInterface="pe.tuenas.prototype.soapservice.budget.BudgetService", serviceName="budgetService") public class BudgetServiceImpl implements BudgetService { @Cacheable(cacheName = "budgetCache") @Override public ListgetBudgetTypeList(String workDate) { return getBudgetTypeDao().findBudgetTypeByFYear( getFinancialYearDao().findFinancialYearByDate(workDate)); } @Cacheable(cacheName = "budgetCache") @Override public List getBudgetTypeListByBusinessYear(String businessYear) { return getBudgetTypeDao().findBudgetTypeByFYear( getFinancialYearDao().findFinancialYearByBusinessYear(businessYear)); } @Cacheable(cacheName = "budgetCache") @Override public List getBusinessCodeList(String workDate) { return getBusinessCodeDao().findBusinessCodeByDate(workDate); } }
@Cacheable annotation선언만으로 캐시기능은 훌륭하게 작동된다.
실제로 한게 너무 없어 황당할 정도...
서비스 영역의 캐시가 완료되면 client영역에서 최초 조회시 원래 속도로 나오고
반복적인 조회에서는 엄청난(?) 속도향상이 이뤄졌다.
cache적용이 유용한 부분은
코드성 데이터 조회 부분,
기본 데이터이지만 반복적으로 호출되는 부분
출력물의 코드, 부서 매핑이 필요한 부분 등일 것이다..
웹상에 공개된 문서나 자료만을 참고해서 급하게 적용하느라
심도있는 이해나 준비가 부족했다.
추후 보완이 필요한 부분이다.
출처 - http://ironheel.tistory.com/44
'Computer Science > Cache' 카테고리의 다른 글
Hazelcast 소개 (0) | 2012.11.06 |
---|---|
Memcached 설치 및 사용 방법 (0) | 2012.11.06 |
Memcached의 확장성 개선 (0) | 2012.11.06 |
memcached를 적용하여 사이트 성능 향상 (0) | 2012.11.06 |
Memcached 구현 소개 (0) | 2012.11.06 |