티베로 리플레이 수행을 위해 제공되는 파일들은 1. 외산 데이터베이스에서 수행 중인 SQL을 파일로 ‘저장’하기 위한 것과 2. 해당 파일을 통해 ‘재현’하기 위한 것 두 종류가 존재한다.
이를 위해 먼저 티베로 리플레이에서 제공하는 바이너리를 살펴보자. 별도의 설치 작업은 없으며 특정 경로에 압축을 해제하면 다음과 같은 디렉토리 구성을 확인할 수 있다
(리플레이 수행은 티맥스 엔지니어가 주도적으로 수행하게 될 것이므로 아주 상세히 살펴볼 필요는 없으나 운영 와스서버의 설정 변경이 필요하므로 기본적인 수행방법만 간단히 안내한다)
리플레이를 통해 SQL 부하 저장을 위해서는 먼저 와스서버에서 현재 사용 중인 JDBC 드라이버가 위치한 곳에 위 바이너리 파일의 jdbc_wrapper 경로에 존재하는 JDBC Wrapper 드라이버를 복사하여 저장해야 한다.
그리고 와스서버의 JDBC 관련 설정 파일에 JDBC Wrapper 드라이버를 사용할 수 있도록 수정을 진행하고 재가동하면 SQL 부하 저장이 시작된다. 다음의 소속 회사 설정 사례를 통해 조금 더 자세히 살펴보도록 하자(소속 회사의 와스서버는 JEUS6를 사용 중이다).
>> $JEUS_HOME/lib/datasource 경로에 $REPLAY_HOME/lib/jdbc_wrapper.jar을 저장한다(JAVA 1.6 : jdbc_wrapper.jar, JAVA 1.5 :jdbc_wrapper5.jar).
>> JEUSMain.xml 설정 변경(DatabaseSource 부분
* 변경 전 설정... OriginalDataSourceName ConnectionPoolDataSource OriginalDataSourceName ...
* 변경 후 설정... com.tmax.replay.jdbc.ConnectionPoolDataSourceWrapper <-- 기존 JDBC 클래스 이름을 제거하고wrapper string을 입력한다.ConnectionPoolDataSource com.tmax.replay.jdbc.ConnectionPoolDataSourceWrapper <-- 기존 JDBC 클래스 이름을 제거하고 wrapper string을 입력한다. ...OriginalDataSourceClassName java.lang.String OriginalDataSourceName <-- OriginalDataSourceClassName property에 기존 JDBC string을 입력한다.loggingDurationInMinute java.lang.Integer 660 <-- 와스 재기동 이후 11시간 동안 부하를 저장한다.jwlFileArchiveSizeInMegabytes java.lang.Long 500 <-- 500MByte 단위로 나누어서 저장한다.jwlDirectory java.lang.String /jwlog <-- jwl 파일이 저장될 경로를 지정한다.... jwrapperDataSourceName java.lang.String ReplayTest <-- 해당 was의 datasource를 통해 저장된 jwl 파일은 ReplayTest라는 이름이 포함된다.
소속 회사의 사례에서 보는 바와 같이 설정 파일의
또한 SQL 부하 저장이 끝이 나더라도
그리고 가장 걱정했던 SQL 저장으로 인해 추가적으로 와스서버에 가해지는 부하도 거의 없었으므로 와스서버 재기동을 제외하고는 큰 어려움 없이 부하 저장이 가능했다는 것을 확인할 수 있을 것이다.
No. | Property Name | Type | Detail |
---|---|---|---|
1 | OriginalDataSource ClassName | java.lang.String | 실제 데이터 소스(WAS Connection Pool) 에서 사용하는 벤더의 JDBC Diver Class Name(FQCN) * 필수 Property |
2 | loggingDuration InMinute | java.lang.Integer | WAS Connection Pool 생성 시각을 기준으로 얼마동안 부하를 로깅하여 jwl 파일을 기록할 지 결정하는 값이다. 기본값은 360(6시간)분이다. 설정 시간 이후에는 로깅하지 않고 Original JDBC의 동작만 수행한다. 모든 DS가 같은 시각에 종료되는 것을 보장하기 위해 최초 생성된 DS의 duration을 기준으로 그 후 생성된 DS의 로깅duration 시간이 생성된 시각으로 비교되어 분단위로 줄어든다. 또한 0으로 설정할 경우 로깅을 하진 않고 JDBC 동작만 수행한다. (Default : 360 /Min) |
3 | loggingEndTime | java.lang.String | loggingDurationInMinute과 비슷하게 로깅의 종료 시점을 설정하기 위한 값이다. 해당 기능이 추가된 이유는 WAS 재부팅 후 loggingDurationInMinute에 의해 로깅되는 시간이 제어가 되는데 여러 DS들을 동시에 Boot할 수 없어 종료 시각이 DS마다 다른 것이 문제이다. 이후 같은 WAS 내에서는 loggingDurationInMinute만 사용해도 종료 시각이 DS마다 같아지게 패치되었지만, 다른 WAS의 DS간의 종료 시각을 맞출 때에는 loggingDurationInMinute 설정으로는 해결이 매우 불편하다. loggingDurationInMinute과 같이 설정되어 있을 경우 해당 Property가 우선순위이며 기본 값은 없다. 해당 Property의 경우 Replay 정식 제품의 정책에 따라 Deprecate될 수도 있다. |
4 | jwlFileArchiveSizeIn Megabytes | java.lang.Long | 하나의 Datasource 마다 생성되는 jwl 파일을 특정 사이즈로 나눠서 로깅하기 위한 옵션이다. 각 파일의 사이즈가 클 경우 jwl 파일을 읽어 rpf 파일을 만드는 과정에서 OOM(Out of Memory) 및 파일이 위치한 디렉터리의 여유 공간이 없을 경우 먼저 생성된 파일을 다른 디렉터리로 옮겨서 Free 0%를 방지하기 위해 필요한 프로퍼티이다. 단위는 MB이며 해당 프로퍼티로 ‘0’ 또는 설정하지 않으면 기본적으로 동작하지 않기 때문에 무한대로 파일 사이즈를 확장한다. * 참고로 설정한 사이즈 값을 철저하게 지키는 것이 아니라 버퍼에 있는 것을 다 파일에 쓴 다음 파일 사이즈가 설정값을 넘어가면 Archive하기 때문에 약간 차이가 있을 수 있다. |
5 | jwlDirectory | java.lang.String |
jwl 파일을 저장할 디렉터리를 설정하는 프로퍼티이며 절대 경로로 지정한다. 설정하지 않으면 기본적으로는 OS User Home에 저장한다. 이 값을 설정할 경우 ‘jwlDirectory’ 아래에 새로운 디렉터리를 만들어서 아카이빙을 하고 디렉터리 이름은 jwl 파일에서 확장자가 없는 이름과 동일하다. (Default : $HOME) |
6 | jwrapperData SourceName | java.lang.String | DataSourceWrapper 인스턴스를 구분하기 위한 ID로 jwl 파일 이름 등에 사용된다. |
7 | streamLogging LengthLimit | java.lang.Integer |
PrepareStatement.setAsciiStream(int parameterIndex , java.io.InputSream x , int length)와 같이 Stream 형식의 데이터에 대해 length 정보와 함께 bind할 경우 기본적으로는 type 정보만 로깅하고 x에 있는 Stream 데이터는 로깅하지 않는다. Stream 데이터를 로깅하려면 byte array를 생성해서 읽어놓고 PrepareStatement.execute()를 호출할 때까지 들고 있어야 하므로 상황에 따라 OutOfMemoryError를 유발할 수 있기 때문이다. Stream 데이터 로깅이 필요할 경우에는 이를 적절한 값으로 설정한다. 이 값을 설정하더라도 PrepareStatement.setAsciiStream(int parameterIndex , java.io.InputSream x)와 같이 length 정보가 없는 bind 호출에 대해서는 로깅하지 않는다. |
참고) 소속 회사와 같이 나스 스토리지 등을 활용하여 여러 대의 와스서버가 동일한 디렉터리를 사용할 수 있도록 구성하면 각 서버에서 생성된 로깅 파일들을 플레이 서버로 전송하는 등의 작업을 줄일 수 있어 편리하다.
재현을 위해서는 먼저 수행할 서버의 OS User Profile에 다음과 같은 환경변수 설정이 필요하다.
재현(플레이) 명령어는 실행 파일, 맵 파일, jwl 파일의 경로와 이름만 명시하면 되므로 저장 프로세스와 마찬가지로 매우 간단히 수행이 가능하다.
참고로 맵 파일은 SQL을 재현할 티베로 데이터베이스 접속 정보를 명시하는 파일로써 IP:Port:DBName으로 작성하여 저장하면 된다(예시: *=127.0.0.1:8888:tibero, 좌측(*)은 SQL이 수행된 외산 DBMS 접속 정보 혹은 *로 명시하면 된다).
참고1) 2.2장 리플레이 구조에서 설명한 것처럼 플레이어(player)는 플랜 파일(rpf file)을 생성하여 해당 파일로 재현을 수행하게 되므로 1차 재현 이후 반복해서 재현 테스트를 수행할 경우 jwl 파일이 아닌 플랜 파일을 명시하여 명령어를 수행하는 것이 효과적이다( 명령어: sh [player.sh 경로] -addrmap [map.txt 경로] -rpf [rpf 파일 경로]).
참고2) 특정 터미널에서 한 개의 jwl 파일을 읽어 부하를 재현할 수도 있지만 로깅된 모든 부하를 유사하게 재현하기 위해서는 여러 개의 재현 명령어를 크론 탭에 스케줄링하여 동시에 수행해야 한다.
참고3) 서로 다른 세션 사이의 Dependency가 있는 동작에 대해서는 보장하지 않으므로 주의해야 한다. 예를 들어, 세션 A에서 row X를 update하는 시각과 세션 B에서 row X 를 select하는 시각이 동일할 경우 (CPU Core 2개에서 concurrent하게 수행 시, JDBC 단에서 수행한 이력이 초 단위로 동일할 경우 등) 어느 쪽 세션의 작업이 먼저 수행되었는지 알 수 없어 부하 재현 시 세션에서 수행한 작업의 순서를 보장하지 않는다. 따라서 소속 회사는 데이터 검증이 아닌 SQL 성능 검증을 위해 주로 리플레이를 사용했다.
player.sh --help Usage : player [-addrmap < arg>] [-debug] -jwl < arg> | -rpf < arg> -addrmap < arg> the absolute path of the address mapping file -debug make log4j logger as debug level -jwl < arg> the absolute path of the jwrapper log file -rpf < arg> the absolute path of the replay plan file -timescale < arg> make player to run faster by n (must be greater than or equal to 1) -convertonly make player to convert jwl to rpf and not to play the rpf(최신 버전에서 추가)
- 강좌 URL : http://www.gurubee.net/lecture/2973
- 구루비 강좌는 개인의 학습용으로만 사용 할 수 있으며, 다른 웹 페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^
- 구루비 강좌는 서비스 제공을 위한 목적이나, 학원 홍보, 수익을 얻기 위한 용도로 사용 할 수 없습니다.