안녕하세요 이정운 입니다.
지난번 강좌에 이어시 이번에는 많이 사용하시는 JDBC 를 활용하여 DataGrid 를 사용하는 작업을 수행해보도록 하겠습니다.
많은 참조 부탁드리며 하단의 강좌를 시작하도록 하겠습니다.
WebSphere eXtreme Scale v8.6
DataGrid 를 활용한 In-Line 캐시 - JDBC
0) DataGrid 를 활용한 In-Line 캐시 – JDBC ?
지
난 강좌에서는 아키텍처 적으로 DB 앞에 WXS 를 In-Line 캐시로 활용하는 In-Memory DataGrid 의 대표적인
아키텍처 구조를 살펴보고 활용하는 간단한 샘플을 돌려봤습니다. 특히, 지난 강좌에서는 JPA 라는 Java EE 표준 OR
Mapping Framework 를 사용하는 형태로 강좌를 진행하여 WXS 가 기본 제공하는 JPALoader 를 사용하여 DB 가
아닌 Grid 를 접근하는 것을 제외하고는 plugin 형태의 Loader 에 의해서 DB 동기화와 같은 나머지 작업들이
자동으로 이루어지는 것을 확인할 수 있었습니다.
그러나 안타깝게도 국내의 현재 많은 프로젝트에서는 JPA 나
Hibernate 라는 OR Mapping 방식보다는 과거부터 이미 많이 사용되었고 조금 더 커스터마이징이 쉬운 JDBC 를
이용한 방식을 많이 사용하고 있으며 어느 정도는 대세로 자리잡고 있습니다. 그럼 이전에 JPA 로 진행했던 강좌의 경험을 가지고
이를 어떻게 JDBC 를 활용한 DB Call 에서 어떻게 WXS 의 Grid 영역을 활용할 수 있는지 살펴보도록 하겠습니다.
즉, JDBC 를 사용할 수 있는 JDBC Custom Loader 를 간단하게 만들어보고 이를 활용하여 In-Memory
DataGrid 의 In-Line 캐시를 활용하는 방안에 대해서 이야기 하도록 하겠습니다.
1) IBM WebSphere eXtreme Scale(WXS) 설치 및 기본 구성
설치 및 구성의 경우는 당연히 지난 강좌의 구성 형태와 동일하게 WXS 가 Client(WAS)와 Server 로 구분되어 설치 되어있다고 가정을 하고 진행하도록 하겠습니다.
2) 테스트를 위한 DB Table, JDBC 애플리케이션 작성
① JDBC 애플리케이션으로 조회, 수정을 수행하기 위한 샘플 DB 와 Table 을 하나 작성
JDBC 애플리케이션이 사용할 DB table 을 생성합니다. 지난 강좌에서는 DB2 를 가지고 했으니 이번에는 Oracle DB 를 활용해서 간단하게 작업해 보도록 하겠습니다.
( create table PERSON(ID Integer not null, Name Varchar(20), Join_date Date, PRIMARY KEY (ID)); )
PERSON 이라는 table 작성을 완료하였으면 조회를 위한 임시 데이터를 하단과 같이 입력합니다.
( Insert into PERSON(ID, Name, Join_date) values(1, 'JungWoon Lee', SYSDATE);
Insert into PERSON(ID, Name, Join_date) values(2, 'JungWoo Lee', '20150105');
Insert into PERSON(ID, Name, Join_date) values(3, 'JungWo Lee', SYSDATE);
Insert into PERSON(ID, Name, Join_date) values(4, 'JungW Lee', '20150106');
Insert into PERSON(ID, Name, Join_date) values(5, 'Jung Lee', SYSDATE);
Insert into PERSON(ID, Name, Join_date) values(6, 'Jun Lee', '20150107'); )
② 조회를 수행하기 위한 간단한 JDBC 애플리케이션 작성
DB 에 임시 데이터를 넣었으면 해당 DB 를 조회할 수 있는 기본 JDBC 프로젝트를 작성합니다. JDBC 애플리케이션인 경우 워낙 다들 잘 아실거라고 판단하여 간단하게 보여만 주고 넘어가도록 하겠습니다.
마찬가지로 JDBC 애플리케이션 테스트를 위한 WAS 설정/배포 등도 이전에 진행한 강좌와 동일하므로 생략하도록 하겠습니다.
3) DataGrid 를 활용한 In-Line 캐시를 위한 JDBC 애플리케이션 변경
이 전 파트에서 JDBC 애플리케이션을 작성해서 간단하게 DB 조회하는 샘플을 만들어서 테스트해봤습니다. 이번에는 동일한 애플리케이션을 활용해서 WXS 의 Data Grid 를 통해서 Data 를 조회하고 없을 경우에 DB 를 조회하여 Data 를 Data Grid 에 자동으로 넣는 JDBC Custom Loader 형태의 애플리케이션을 작성해 보도록 하겠습니다.
JDBC
Custom Loader 관련한 해당 소스부분은 github 에 공개된 Billy Newports 님의 자료를 많이
활용하였습니다. (Billy Newports 는 IBM 의 DE 로서 WXS 의 founder 입니다. 다양한 경험과 노하우가
녹아있는 많은 WXS 관련 sample code 와 utility code 를 github 를 통해서 공개하고 있습니다. 사실
프로그래밍을 조금 하실 수 있는 분들은 제 강좌를 보기보다흔 해당 github 의 여러 소스를 분석하는 것이 이해가 더 빠르실 수
있습니다.
https://github.com/bnewport/Samples )
① client 입장으로 WAS 에 배포되고 사용될 servlet 형태의 WAR 애플리케이션 작성
우선 client 입장이 되는 servlet 을 보유하는 WAR 애플리케이션을 하단과 같이 간략하게 작성합니다.
이전에 참고한 샘플과 거의 동일하며 다만 지난 강좌에서 이야기 한것과 같이 DB 가 아니라 WXS 가 제공하는 API 를 사용하여 Grid 에 접속해서 작업하는 방식의 차이만 있습니다.
select 만이 아니라 나머지 delete, update, insert 관련 메소드를 살펴봐도 거의 유사한 것을 확인할 수 있습니다. (좀 더 자세한 사항은 첨부해드린 샘플 코드를 직접 확인해보시기 바라겠습니다.)
② WXS 의 Grid 에서 실제로 DB 동기화를 수행하게될 JDBC Custom Loader 작성
이
번 강좌의 가장 중요한 부분으로 WXS 의 Grid 에 거주하면서 client 가 Grid 로 CRUD 작업을 수행할 경우에 DB
동기화 및 응답을 전해주는 Custom 형태의 JDBC Loader 를 작성해 보도록 하겠습니다.
Jar 를
생성하기 위한 Java 프로젝트를 하나 생성한 후 자료형으로 사용될 Person class 를 복사하고 필요한 utility
jar 를 build path 에 추가합니다. 하단에 보여드린 다양한 utility jar 들은 JDBCLoader 와
JDBCTxCallBack 을 만드는 과정에서 필요한 jar 라이브러리들 입니다. DB 접속을 위해서 ojdbc6.jar 가
필요하며 standalone server 형태의 WXS 에서 DB Connection pool 형태로 구성하기 위한 Apache
common dbcp2 프로젝트를 사용할 것이라 commons-dbcp2, commons-logging, commons-pool2
라이브러리를 추가하였습니다. (마지막에 있는 objectgrid.jar 는 WXS 개발을 위한 라이브러리로 개발시에는 필요하나
어짜피 WXS 엔진에서 제공되는 것이므로 실제 WXS 의 Grid 를 시작시킬 때는 필요하지 않습니다.)
여
기서 JDBCLoader 는 실제적으로 지난 강좌에서 보여드린 JPALoader 와 같이 DB 동기화 작업을 수행하는 Loader
역할을 수행하며 JDBCTxCallBack 은 이러한 작업을 수행하는 과정안에서 트랜잭션 처리를 수행하는 callback
class 입니다. 그럼 지금 부터는 JDBCLoader 에 대해서 좀 더 자세히 살펴보도록 하겠습니다.
JDBCLoader
와 같은 Custom Loader 를 만들 경우에는 기본적으로 제공되는 Loader 라는 interface 를 상속받아서
여기서 사전에 정의된 preloadMap, get, batchUpdate 메소드를 구현해주어야 합니다. get() 메소드는
select 구문이 수행될 경우에 수행되는 메소드이며 하단의 snippet 을 보시면 아시겠지만 실제 DB 에 select 구문을
수행하는 형태로 구성되어 있습니다.
여
기서 중요하게 보실 부분이 실제로 connection 을 가지고 오는 tcb.getConnection() 부분입니다. 여기서
tcb 인스턴스는 JDBCTxCallBack class 의 인스턴스로서 실제로 트랜잭션 처리를 수행하는 callback class
입니다. 즉, JDBCLoader 가 실제로 작업을 수행하는 것처럼 보이지만 이안에 있는 트랜잭션은 callback class 인
JDBCTxCallBack class 에서 처리됩니다. 그럼 이제 JDBCTxCallBack 를 살펴보도록 하겠습니다.
우
선 JDBCTxCallBack class 도 기본적으로 사전에 WXS 에서 정의된 TransactionCallback
interface 를 구현해야 합니다. 해당 interface 는 initialize, begin, commit,
rollback, isExternalTransactionActive 메소드를 가지고 있으므로 해당 메소드를 구현해야 합니다. 이름
그대로 initialize() 메소드는 초기화 작업을 수행하고 begin() 은 transaction 의 begin 과
매핑됩니다. 당연히 commit(), rollback() 도 transaction 의 각각의 메소드에 매핑됩니다. 마지막으로
isExternalTransactionActive() 는 WXS 가 WebSphere Applicaion Server 위에서
구동될 때 WAS 의 transaction ID 와의 연동을 위해서 사용되는데 이번 강좌에서는 WXS 를 standalone
형태로 구동하는 경우이므로 본 강좌에서 구체적인 언급은 생략하도록 하겠습니다.
Initializae() 메소드는
하단의 snippet 을 보시면 아시겠지만 Transaction ID 와 매핑한 connection 을 보관할 slot 을
생성하고 DataSource 를 설정하는 등의 초기화 작업을 수행합니다.
(connection 을 생성하고 바로 close 하는 작업은 초기에 connection 체크를 위한 작업입니다.)
실
제로 메소드 내부에서 호출되는 setupDataSource() 를 살펴보면 아시겠지만 Apache common dbcp2
라이브러리를 이용해서 DB Connection pool 을 생성하고 DataSource 를 넘기는 형태로 구성되어 있습니다.
(실제로 해당 부분은 Apache common dbcp2 의 예제를 그대로 가져왔습니다.)
commit()
메소드도 역시 이름 그대로 트랜잭션의 commit 을 수행하고 connection 을 close 하는 형태로 구성되어 있습니다.
일반적인 트랜잭션의 commit 을 처리하는 메소드와 거의 동일하지만 이전에 slot 에 담아둔 connection 을 꺼내서
commit을 수행하는 부분만 다른 것을 아실 수 있습니다.
마 지막으로 확인해볼 메소드는 JDBCLoader class 에서 connection 을 가지고오기 위해서 사용하는 JDBCTxCallback class 의 getConnection() 메소드입니다. 하단의 코드 snippet 을 보면 아시겠지만 slot 에 connection 이 있는지 먼저 체크해서 있으면 해당 slot 에 있는 connection 을 반환하고 그렇지 않으면 connection 을 생성한 후 이를 slot 에 저장하는 형태로 구성되어 있습니다. 즉, JDBCLoader class 에서 작업을 위해서 생성된 connection 을 결국 JDBCTxCallback class 에서 처리하는 것을 이해하실 수 있을 것 입니다.
참
고: client 용 애플리케이션과 Loader 를 다 개발한 후에 client 용 애플리케이션에서 개발된 Loader 의
transaction 사용을 위해서 하단과 같이 JDBCTxCallback class 의 껍데기를 넣어주셔야 합니다.
결
국, 위에 언급된 소스를 다 작성하셨으면 하단과 같이 JDBC Custom Loader 인 JDBCCustomLoader 라는
Java 프로젝트 하나와 client 로 사용될 SearchJDBC 라는 동적 웹 프로젝트 하나의 구조가 나오게 됩니다.
이전 파트에서 JDBC 애플리케이션이 작성되었으면 이제 JDBCLoader plugin 을 적용하여 WXS Server 를 구동하기 위하여 설정작업을 진행하도록 하겠습니다.
① IBM WXS 의 카탈로그 서버와 컨테이너 서버의 구성을 결정하는 설정 정보 파일 준비
중요 부분 JDBCObjectGrid.xml
<objectGrids>
<objectGrid name="PersonGrid" txTimeout="60">
<bean id="TransactionCallback" className="com.ibm.juwlee.wxs.JDBCTxCallback">
</bean>
<backingMap name="Person" lockStrategy="PESSIMISTIC" pluginCollectionRef="Person"/>
</objectGrid>
</objectGrids>
<backingMapPluginCollections>
<backingMapPluginCollection id="Person" >
<bean id="Loader" className="com.ibm.juwlee.wxs.JDBCLoader">
</bean>
</backingMapPluginCollection>
</backingMapPluginCollections>
ObjectGrid 설정 파일을 보시면 JPALoader 를 사용했던 경우와 거의 동일하며 다만 이전 파트에서 만든 JDBCLoader 와 JDBCTxCallBack 으로만 변경을 해주면 됩니다.
중요 부분 JDBCObjectGridDeployment.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 준비
대부분의 설정은 지난번에 설명드린 내용과 비슷합니다. 간단한 테스트를 위해서 제가 테스트시에 간단하게 만들었던 시작 스크립트를 첨부드리오니 참고하시기 바라겠습니다.
카탈로그 서버
startXsServer cat1 -listenerPort 4809 -JMXServicePort 4899 -catalogServiceEndPoints cat1:kr050578:6600:6601
컨테이너 서버
startXsServer
c1 -listenerPort 5001 -haManagerPort 5002 -objectGridFile
D:\00.biz_work\01.SWG\11.WXS\WXS86_guide\JDBCObjectGrid.xml
-deploymentPolicyFile
D:\00.biz_work\01.SWG\11.WXS\WXS86_guide\JDBCObjectGridDeployment.xml
-catalogServiceEndPoints kr050578:4809 -jvmArgs
-javaagent:C:\IBM\WebSphere85\eXtremeScale\ObjectGrid\lib\wxssizeagent.jar
-cp
D:\00.biz_work\01.SWG\11.WXS\WXS86_guide\JDBCCustomLoader.jar;D:\00.biz_work\01.SWG\11.WXS\WXS86_guide\lib\ojdbc6.jar;D:\00.biz_work\01.SWG\11.WXS\WXS86_guide\lib\commons-dbcp2-2.0.1.jar;D:\00.biz_work\01.SWG\11.WXS\WXS86_guide\lib\commons-pool2-2.3.jar;D:\00.biz_work\01.SWG\11.WXS\WXS86_guide\lib\commons-logging-1.2.jar
컨
테이너 서버 설정은 이전 강좌와 대부분 동일하며 DB 연결을 위한 Oracle JDBC Driver 인 ojdbc6.jar 와
Apache common dbcp2 를 사용하기 위한 commons-dbcp2-2.0.1.jar,
commons-pool2-2.3.jar, commons-logging-1.2.jar 를 classpath 로 잡는 것만 다릅니다.
이를 이용해서 WXS 의 카탈로그 서버와 컨테이너 서버를 구동하면 하단과 같은 결과를 확인할 수 잇습니다.
xscmd -c showMapSizes -cep kr050578:4809
5) DataGrid 를 활용한 In-Line 캐시 테스트 – JDBCLoader
작성된 애플리케이션을 WAS 에 모두 배포한 후에 해당 애플리케이션에서 WXS 의 Grid 를 조회하는 호출을 수행해보면 이전 강좌와 동일하게 하단과 같이 정상으로 결과가 나오는 것을 확인할 수 있습니다.
( http://localhost:9080/search/ActionJDBCwithGrid )
정상적으로 JDBC 호출이 조회가 된 후에 Grid 내부를 확인해보면 조회된 DB 내용이 자동으로 Grid 에 캐시된 것을 확인가능합니다.
xscmd -c showMapSizes -cep kr050578:4809
xscmd -c findByKey -g PersonGrid -m Person -fs ".*" -rv -cep kr050578:4809
다음으로 임의의 데이터를 DB 에 실제적으로 Data 를 Insert 하는 호출을 수행합니다. (실제적으로는 Grid 에 insert 하는 작업입니다.)
상단의 insert 작업이 완료된 후에 Grid 를 조회해보면 Object 가 추가적으로 insert 된 것을 확인할 수 있습니다.
마 찬가지로 해당 작업 완료된 후에 DB 에서 sqlplus 를 이용해서 select 를 해보면 insert 한 내용이 DB 에 문제없이 들어와있는 것을 확인 가능합니다. 즉, Grid 에 Insert 작업을 수행하게 되면 설정된 JDBCLoader 에 의해서 자동으로 DB 까지 동기화가 되는 것을 확인할 수 있습니다.
다음으로 DB 에 존재하는 Data 를 Update 하는 호출을 수행합니다. (실제적으로는 Grid 에 캐시된 Data 를 update 하는 작업입니다.
상단의 update 작업이 완료된 후에 Grid 를 조회해보면 update 작업이기 때문에 이전과 동일한 2개의 캐시된 Object 를 확인할 수 있습니다.
그 러나 Grid 에 update 작업을 수행하게 되면 설정된 JDBCLoader 에 의해서 자동으로 DB 까지 동기화가 되어 sqlplus 에서 확인시에 update 한 내용이 DB 에 문제없이 반영되어 있는 것을 확인 가능합니다.
마지막으로 DB 에 존재하는 Data 를 Delete 하는 호출을 수행합니다. (실제적으로는 Grid 에 캐시된 Data 를 delete 하는 작업입니다.
상단의 update 작업이 완료된 후에 Grid 를 조회해보면 delete 작업이기 때문에 하나의 캐시된 Object 가 삭제되어 하나만 남은 것을 확인할 수 있습니다.
이
전과 마찬가지로 Grid 에 delete 작업을 수행하게 되면 설정된 JDBCLoader 에 의해서 자동으로 DB 까지 동기화가
되어 sqlplus 에서 확인시에 delete 한 내용이 DB 에 문제없이 반영되어 있는 것을 확인 가능합니다.
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
Integrating WebSphere eXtreme Scale transactions with other transactions
http://www.ibm.com/developerworks/websphere/techjournal/1205_jolin/1205_jolin.html
GitHub - bnewport/Samples
https://github.com/bnewport/Samples
댓글