본문 바로가기
IBM - old/IBM WXS

WXS 를 활용한 In-Memory DataGrid 맛보기 03 - DataGrid 를 활용한 In-Line 캐시 (JPA)

by freeman98 2016. 6. 7.

안녕하세요 freeman 입니다.

이번에는 In-Memory DataGrid 솔루션인 WXS 를 활용한 In-Line 캐시- JPA 관련 강좌입니다.

많은 참조 부탁드리며 하단의 강좌를 시작하도록 하겠습니다.



WebSphere eXtreme Scale v8.6
DataGrid 를 활용한 In-Line 캐시 - JPA


0) DataGrid 를 활용한 In-Line 캐시란?

이 미 설명을 드렸지만 IBM WXS 란 IBM WebSphere 제품 중에서 분산 캐싱 플랫폼(distributed caching platform) 을 제공할 수 있는 Middleware 제품이며 이를 통해서 In-Memory DataGrid 를 구성할 수 있습니다. 여기서 분산 캐싱 플랫폼이란 다수의 JVM 에 분산되어 있는, 사용하지 않는 메모리를 취합하여 하나의 논리적인 캐시처럼 사용하는 기술을 의미하며 언급한 것과 같이 In-Memory DataGrid 라고 불리워집니다. 이를 잘 활용하면 거대한 트랜잭션 볼륨을 가진 중요한 비즈니스 어플리케이션에 지속적인 고성능과 확장성, 가용성을 실현해 줄 수 있습니다.

이전 강좌들에서는 IBM WXS 를 활용하여 HTTP 세션 데이터를 저장하는 방안과 원하는 Java 객체를 저장하는 글로벌 캐시구성 방안에 대해서 간단한 샘플과 함께 설명을 진행하였습니다. 이번 강좌에서는 데이터가 저장되어 있는 DB 앞 단에 WXS 를 In-Line 캐시 계층으로 두고 활용하는 간단한 샘플을 살펴보도록 하겠습니다. 하단의 그림을 보면 이해가 도움이 될텐데 In-Line 캐시란 DB 앞 단에 캐시영역인 Grid 를 두고 마치 Grid 가 DB 인 것처럼 작동되는 방식을 의미합니다. 이 경우 Grid 와 DB 의 동기화 작업은 WXS 에서 Loader 라는 plugin 을 통해서 자동으로 처리합니다. 


특 히, 이번 강좌에서는 JPA 라는 Java EE 표준 OR Mapping Framework 를 사용하는 형태로 강좌를 진행하도록 하며 미리 만들어서 제공하는 JPALoader 라는 plugin 을 이용해서 WXS 의 Grid 와 DB 의 동기화를 별도로 코딩하거나 작업하는 것이 아니라 Grid 에 데이터만 넣으면 나머지는 plugin 을 통해서 자동으로 이루어지는 구조를 생성하고 테스트 해보도록 하겠습니다. 



1) IBM WebSphere eXtreme Scale(WXS) 설치 및 기본 구성
설치 및 구성의 경우는 지난 강좌인 글로벌 캐시 구성 형태와 동일하게 WXS 가 Client(WAS)와 Server 로 구분되어 설치 되어있다고 가정을 하고 진행하도록 하겠습니다. 



2) 테스트를 위한 DB Table, JPA 애플리케이션 작성
① JPA 애플리케이션으로 조회, 수정을 수행하기 위한 샘플 DB 와 Table 을 하나 작성
DB 데이터를 자동으로 캐시하고 조회하는 WXS 를 활용한 In-Memory DataGrid 구성을 위하여 Sample DB 를 활용하여 새롭게 table 을 생성합니다. WXS 에 대한 기본개념에 대한 이해를 돕는 목적이기 때문에 가급적 간단한 table 을 작성합니다.
(create table PERSON(ID Integer not null GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1, NO CACHE), Name Varchar(20), Join_date Date, PRIMARY KEY (ID)))



PERSON 이라는 table 작성을 완료하였으면 조회를 위한 간단한 임시 데이터를 하단과 같이 입력합니다.
(Insert into PERSON(Name, Join_date) values('JungWoon Lee', CURRENT DATE)
Insert into PERSON(Name, Join_date) values('JungWoo Lee', DATE ('2015-1-5'))
Insert into PERSON(Name, Join_date) values('JungWo Lee', CURRENT DATE)
Insert into PERSON(Name, Join_date) values('JungW Lee', DATE ('2015-1-6'))
Insert into PERSON(Name, Join_date) values('Jung Lee', CURRENT DATE)
Insert into PERSON(Name, Join_date) values('Jun Lee', DATE ('2015-1-7')) )


 
② 조회를 수행하기 위한 간단한 JPA 애플리케이션 작성
DB 에 임시 데이터를 넣었으면 해당 DB 를 조회할 수 있는 기본 JPA 프로젝트를 작성합니다. 이를 위해서 하단과 같이 eclipse 를 이용해서 JPA 프로젝트를 하나 만듭니다.
(이때 JPA 버전은 2.0 을 선택하고 WAR 프로젝트를 넣기 위하여 EAR 프로젝트도 같이 생성합니다.)


JPA 프로젝트 생성중에 Connection 관련한 마법사가 나오면 DB 에 연결하는 작업을 수행하기 위하여 ‘Add connection’ 버튼을 클릭합니다.

 


Connection profile 에서는 연결되는 DB를 선택하고 다음을 클릭합니다.


연결을 위한 User/Password 정보를 입력한 후에 Driver 설정을 위하여 Drivers 메뉴 옆의 아이콘을 클릭합니다. 


 
DataBase 기본 정보를 선택한 후에 DB Driver jar 파일을 설정하기 위하여 JAR List 탭을 클릭합니다. 


 
Driver Jar 파일의 위치를 기본이 아니라 가지고 있는 DB Driver 위치로 변경한 후 OK 를 클릭합니다. 


요약정보를 확인하고 이상이 없다면 Finish 를 클릭합니다.마지막으로 정보를 확인하고 Finish 를 클릭하여 JPA 생성을 완료합니다.


 
여기까지 작업을 문제없이 수행했다면 하단과 같은 구조로 JPA 프로젝트가 생성된 것을 확인할 수 있습니다.


이제 실제로 DB 와 연결된 JPA 소스를 자동으로 생성하기 위하여 프로젝트에서 마우스 우 클릭 후에 JPA Tools > Generate Entities from Tables 를 클릭합니다. 


 

이전에 만들어진 Connection 에서 table 을 선택하는 마법사가 나오면 방금 생성한 Person table 을 선택하고 다음을 클릭합니다.


이전에 Person table 을 생성할 때, ID 값을 자동생성 했기 때문에 Key generator 를 identity 로 선택하고 package 명도 입력한 후 완료를 클릭합니다.


해당 작업이 정상적으로 완료되면 하단과 같이 Person 이라는 Entity class 가 Tool 에 의해서 자동으로 생성된 것을 확인할 수 있습니다.


마지막으로 JPA 프로젝트의 설정(persistence.xml) 부분에서 JTA Data Source 명을 입력합니다.
(향후 해당 JNDI 이름으로 WAS 에서 JDBC Data source 를 생성해서 사용할 것입니다.)


JPA 프로젝트를 잘 만들었으면 이를 조회하기 위하여 샘플 servlet 를 이용한 동적 웹 프로젝트를 하단과 같이 만들고 이를 IBM WAS 에 배포합니다. 하단의 내용은 Servlet 의 snippet 으로서 전체코드는 첨부된 어플리케이션을 참조하시기 바라며 하단의 snippet 만으로도 JPA 조회 servlet 을 만드는 것은 어렵지 않으실 것 입니다. 첨부한 것을 간단히만 설명드리자면 SearchPersonJPA에서 JPA 호출을 위한 retrievePerson 메소드로서 JPA 방식으로 EntityManagerFactory 를 받아와서 EntityManager 를 생성하고 이를 이용해 DB 의 select 작업(EntityManager 의 find() 메소드)을 진행하는 샘플입니다. 다만 본 강좌는 WXS 를 활용한 In-Memory DataGrid 를 사용하는 강좌이지 JPA 프로그래밍 강좌가 아니기때문에 해당 소스 설명을 일일이 진행하지는 않도록 하겠습니다.(잘 이해가 안되시는 분은 구글신에 도움을 받아 검색해보면 쉽게 이해하실 수 있습니다.)

 
 
3) JPA 테스트를 위한 WAS 설정 및 준비
JPA 테스트를 위하여 client 로 사용할 WAS 에 DB 를 연결하기 위한 정보인 JDBC Provider 와 Datasource 를 작성합니다.
(이 부분은 다른 강좌에서도 이미 많이 다뤘으므로 “하나씩 쉽게 따라 해보는 IBM WAS v7 시리즈 - 5. DB연결” 강좌(http://www.websphere.pe.kr/xe/index.php?mid=was_lecture&page=5& amp;document_srl=1674)  나 다른 기본 강좌들을 참고하시기 바라겠습니다.)
 

이후 이전 파트에서 작성하였던 샘플 애플리케이션을 IBM WAS 로 배포합니다.
 

 
4) 샘플 JPA 애플리케이션 테스트
이제 JPA 테스트를 위한 준비가 다 된 것이므로 샘플 테스트를 수행해보도록 하겠습니다. 먼저 배포된 애플리케이션의 만들어둔 서블릿 페이지를 호출합니다.
(http://localhost:9080/SerchJPA/SerchPersonJPA)


호출이 정상적으로 완료되면 Sample DB 에 넣어둔 data 를 하나 조회해봅니다. 

Sample DB 에 없는 ID 도 테스트로 조회해 봅니다.


여기까지 동일한 결과를 확인하셨다면 문제없이 샘플 JPA 애플리케이션 테스트가 완료된 것입니다.



5) IBM WXS 를 활용한 In-Line 캐시를 위한 JPA 애플리케이션 변경
이 전 파트까지는 기본적으로 JPA 애플리케이션을 작성해서 간단하게 DB 조회하는 샘플을 만들어서 테스트해봤습니다. JPA 가 동작하는 방식을 보여주는 간단한 샘플이였고 이제 해당 강좌의 본론으로 들어가서 동일한 애플리케이션을 활용해서 WXS 의 Grid 를 통해서 Data 를 조회하고 없을 경우에 DB 를 조회하여 Data 를 Grid 에 자동으로 넣고 클라이언트에 반환해주는 In-Line 캐시를 활용하는 애플리케이션을 작성해 보도록 하겠습니다. 이를 위해서는 Loader 라는 plugin 이 필요하게 되며 하단과 같은 구조로 사용됩니다. (기본적으로 IBM WXS 는 JPALoader 를 제공합니다.)



이 를 좀 더 보강해서 설명하자면 Write-Through 방식의 Grid 사용방식으로 JPA 를 사용해서 DB 조회 하는 것과 거의 동일하게 API 만 변경해서 작업하면 실제 뒷단의 WXS 와 DB 에는 JPALoader 라는 미리 만들어진 plugin 을 사용하여 필요한 Grid 와 DB 의 동기화와 같은 작업을 알아서 처리해줍니다. Write-Through 라는 방식은 Write-Behind 방식과 상대되는 말로 IMDG 로 사용되는 WXS 와 DB 간에 동기화를 Sync 방식(바로)으로 할 것이냐 aSync 방식(나중에)으로 할 것이냐의 차이입니다. 예를 들어서 Write-Through 방식은 CRUD 와 같은 DB 작업이 발생될 때 WXS 와 DB 간에 매번 바로 동기화(트랜잭션 연결)를 수행하는 것이고 Write-Behind 방식은 CRUD 작업이 벌어져도 WXS 와 DB 간에 매번 바로 동기화 하는 것이 아니나 지정된 횟수나 시간 방식으로 동기화가 이루어지는 작업입니다. 현재 강좌에서는 우선 Write-Through 방식으로 처리되는 형태로 예제를 진행하도록 하겠습니다.

이 제 해당 방식으로 애플리케이션을 작성해보겠습니다. 우선 이전 단순 JPA 샘플에서는 없었지만 WXS 에 데이터를 저장하기 위해서 카탈로그 서버에 연결해서 WXS 의 ObjectGrid 객체를 받아오는 소스 부분이 하단과 같이 추가되어야 합니다. 하단에 snippet 을 보시면 아시겠지만 이전에 진행한 WXS 를 활용한 글로벌 캐시 구성과 거의 동일하며 다만 String 을 반환받는 것이 아니라 JPA 기반으로 되어 있는 entity class 인 Person 을 리턴 받는 형태만 조금 다릅니다.


또 한, 이전처럼 WAS 에서 JPA 를 수행하는 형태가 아니라 실제적으로 JPA 의 CRUD 작업은 JPALoader 라는 plugin 을 통해서 standalone 형태로 동작하는 WXS의 Grid 와 DB 간에서 동작하고 그 결과만 client 입장인 WAS 에 넘겨주는 형태입니다. 그러므로 실제로 Java SE 를 쓰고 standalond 형태로 구동시킬 WXS 가 JPA 를 사용하기 위해서 apache 의 OpenJPA 를 사용하는 형태의 구성을 persistence.xml 파일에 추가합니다. (WAS 도 기본적으로는 apache 의 OpenJPA 의 구현체를 확장해서 사용하며 OpenJPA 를 지원할 수 있습니다.)  하단을 보시면 아시겠지만 DB driver 나 접속 정보를 property 형태로 넣어주시기만 하면 됩니다.


마지막으로 변경된 애플리케이션을 WAS 에 배포하고 이전과 다르게 JPA 형태로 자동 작성된 PersonJPA 프로젝트는 PersonJPA.jar 로 추출하여 별도로 보관합니다.(향후 해당 jar 를 가지고 WXS 를 기동할 때 참조해야 합니다.)


6) IBM WXS 를 활용한 In-Line 캐시를 위한 WXS Server 설정

애플리케이션이 작성되었으면 이제 JPALoader plugin 을 적용하여 WXS Server 를 구동하기 위하여 설정작업을 진행하도록 하겠습니다.

① IBM WXS 의 카탈로그 서버와 컨테이너 서버의 구성을 결정하는 설정 정보 파일 준비

중요 부분 JPAObjectGrid.xml
<objectGrids>
        <objectGrid name="PersonGrid" txTimeout="60">
            <bean id="TransactionCallback" className="com.ibm.websphere.objectgrid.jpa.JPATxCallback">
                <property name="persistenceUnitName" type="java.lang.String" value="PersonJPAwithWXS"/>
            </bean>
            <backingMap name="Person" lockStrategy="PESSIMISTIC" pluginCollectionRef="Person"/>
        </objectGrid>
    </objectGrids>
    <backingMapPluginCollections>
      <backingMapPluginCollection id="Person" >
          <bean id="Loader" className="com.ibm.websphere.objectgrid.jpa.JPALoader">
              <property name="entityClassName" type="java.lang.String" value="com.ibm.juwlee.jpa.Person"/>
          </bean>
      </backingMapPluginCollection>
    </backingMapPluginCollections>

ObjectGrid 설정 파일을 보시면 이전과 다른 com.ibm.websphere.objectgrid.jpa.JPATxCallback 빈이 보이는데 해당 빈은 이름 그대로 JPA 트랜잭션 콜백을 위해 사용하는 빈으로 JPA 를 사용하여 DB 동기화를 할 때 사용하는 트랜잭션용 빈으로 이해하시면 됩니다. 즉, JPA 관련 트랜잭션을 담당하고 무엇을 가지고 트랜잭션을 수행하는 가를 알리기 위해서 persistence.xml 에서 정의한 persistenceUnitName 을 프로퍼티로 넣어주면 됩니다.

그 다음으로 보실 부분이 backingMapPluginCollections 이고요 해당 backingMap 에 Plugin 을 연결하는 설정입니다. 여기서는 JPALoader 라고 미리 만들어져서 제공되는 Loader Plugin 을 연결하는 설정입니다. 이전에 언급한 것처럼 Loader 는 Grid 에 저장된 캐시 객체와 DB 의 동기화 작업을 별도 코딩없이 자동으로 수행해주는 역할을 하는 plugin 입니다.

중요 부분 JPAObjectGridDeployment.xml
<objectgridDeployment objectgridName="PersonGrid">
        <mapSet name="PersonMapSet" numberOfPartitions="5"  minSyncReplicas="0" maxSyncReplicas="1" developmentMode="true">
            <map ref="Person"/>
        </mapSet>
    </objectgridDeployment>
</deploymentPolicy>

ObjectGridDeployment 설정 파일은 이전 강좌인 글로벌 캐시와 거의 비슷하므로 생략하겠습니다.

② IBM WXS 의 카탈로그 서버와 컨테이너 서버의 구동을 위한 script 준비
나머지 설정은 지난 강좌와 동일하게 사용하도록 하며 WXS 에서 OpenJPA 를 구동하기 위해서 IBM WAS 설치디렉토리/runtimes/com.ibm.ws.jpathinclient_8.5.0.jar 위치를 확인해 둡니다.



간단한 테스트를 위해서 제가 테스트시에 간단하게 만들었던 시작 스크립트를 첨부드리오니 참고하시기 바라겠습니다.

카탈로그 서버
startXsServer cat1 -listenerPort 4809 -JMXServicePort 4899 -catalogServiceEndPoints cat1:kr050578:6600:6601

컨테이너 서버
startXsServer c1 -listenerPort 5001 -haManagerPort 5002 -objectGridFile D:\00.biz_work\01.SWG\06.WASv85\WASv855_guide\JPAObjectGrid.xml -deploymentPolicyFile D:\00.biz_work\01.SWG\06.WASv85\WASv855_guide\JPAObjectGridDeployment.xml -catalogServiceEndPoints kr050578:4809 -jvmArgs  -javaagent:C:\IBM\WebSphere85Base\AppServer\runtimes\com.ibm.ws.jpa.thinclient_8.5.0.jar -javaagent:C:\IBM\WebSphere85\eXtremeScale\ObjectGrid\lib\wxssizeagent.jar -cp D:\00.biz_work\01.SWG\09.SampleSource\WXS\PersonJPA.jar;D:\eclipses\eclipse_luna_wxs\utilLib\db2jcc.jar


컨 테이너 서버 설정은 이전 강좌와 약간 다른데 “-javaagent:” 옵션을 사용해서 OpenJPA 를 구동하기 위하여 IBM 이 강화한 JPA thin client 라이브러리를 참조하고 마찬가지로 실제 JPA 프로젝트인 PersonJPA.jar 파일과 DB2 JDBC 드라이버 jar 를 classpath 에 포함하도록 되어 있습니다. 이는 standalone 으로 구동되는 WXS 가 OpenJPA 를 활용하여 실제 DB 랑 작업을 수행하기 때문에 해당 클래스들을 볼 수 있도록 참조하는 것입니다.( wxssizeagent.jar 성능 튜닝용이라 반드시 사용할 필요는 없습니다.)

이를 이용해서 WXS 의 카탈로그 서버와 컨테이너 서버를 구동하면 하단과 같은 결과를 확인할 수 잇습니다.
xscmd -c showMapSizes -cep kr050578:4809


이 에 추가하여 참고로 haManagerPort 만 변경하여 c2 라는 컨테이너 서버를 하나 더 기동하게 되면 하단과 같이 두 개의 컨테이너가 구동된 것을 확인할 수 있으며 보다 중요한 것은 하나의 컨테이너를 더 두게 되면 복제본이 같이 위치하는 것을 보실 수 있습니다.
(단, 해당 부분은 ObjectGridDeployment 설정의 developmentMode 가 true 이기 때문에 한대의 HW 만으로도 해당 부분을 확인할 수 있는 것입니다. 일반적으로 프로덕션 환경은 여러 대의 서버를 권장하고 WXS 의 권장도 마찬가지 이므로 해당 설정이 아니라면 각 HW 별로 원본과 복제본이 분리해서 위치하게 됩니다.)


현 재 컨테이너에 원본과 복제본이 몰아져 있는데 시간이 지나면 최적화 알고리즘에 의해 자동으로 밸런싱 됩니다. 또는 하단과 같이 수동으로 밸런싱 명령을 수행하는 방안을 통해 컨테이너 서버의 Partition 에 대한 밸런싱 조정이 가능합니다.
xscmd -c balanceShardTypes -cep kr050578:4809


 
7) IBM WXS 를 활용한 In-Line 캐시 테스트
작 성된 애플리케이션을 WAS 에 모두 배포한 후에 해당 애플리케이션에서 WXS 의 Grid 를 조회하는 호출을 수행해보면 하단과 같이 정상으로 결과가 나오는 것을 확인할 수 있습니다. 뿐만 아니라 연속적 호출을 통해서 WXS 의 Grid 로 캐시된 데이터를 반환하는 두 번째 호출이 첫 번째 호출에 비해 성능이 비약적으로 상당히 좋아진 것을 확인할 수 있습니다.
 
뿐 만 아니라 다시한번 xscmd 명령을 이용해서 Grid 내부를 살펴보면 하단과 같이 실제로 DB 의 데이터가 향후 캐시로 사용하기위해 Grid 에 저장된 것을 확인할 수 있습니다. 즉, 처음에는 Grid 에 데이터가 없으므로 DB 조회를 수행하는 것이고 이 때 조회된 DB 데이터는 Grid 에 저장되어 이 후 부터의 호출은 DB 까지 가지 않고 캐시 데이터가 존재하는 Grid 에서 원하는 결과를 리턴해주는 형태입니다.
xscmd -c showMapSizes -cep kr050578:4809


 
여기까지 문제없이 따라오셨다면 WXS 를 활용한 In-Memory DataGrid 구성 및 이를 활용한 테스트가 완료된 것입니다.



9) 참고 자료

IBM WebSphere eXtreme Scale Version 8.6 Information Center
http://pic.dhe.ibm.com/infocenter/wxsinfo/v8r6/index.jsp?topic=%2Fcom.ibm.websphere.extremescale.doc%2Fwelcome%2Fwelcome_xs.html

WebSphere eXtreme Scale v8.6 Key Concepts and Usage Scenarios
http://www.redbooks.ibm.com/abstracts/sg247683.html?Open

WebSphere eXtreme Scale Best Practices for Operation and Management
http://www.redbooks.ibm.com/abstracts/sg247964.html?Open


댓글