DB Connection Pool과 JDBC
본 장에서는 JEUS에서 제공하는 JDBC Connection Pooling의 기본 메커니즘과 JDBC Connection Pool의 사용 방법 그리고 JEUS 도메인 구조에서의 데이터소스 관리 방법 등에 대해 설명한다.
1. 개요
웹 애플리케이션은 정보 저장이 필요할 때 주로 DB를 이용한다. 또한 JEUS와 같은 웹 애플리케이션 서버(web application server, 이하 WAS)는 애플리케이션에 Connection Pooling 등 DB 의존적인 서비스를 제공하기 위하여 DB와 통신할 필요가 있다. 이러한 필요를 보다 체계적이고 효율적으로 충족시키기 위해 DB 클라이언트들과 DB 간 인터페이스를 정의한 것이 바로 Java Database Connectivity(JDBC) 표준이다.
JDBC 표준은 애플리케이션의 DB Connection 사용 방법 및 SQL 작업 수행 방법에 대해 기술하고 관련 API를 제공한다. JDBC 표준에 관한 자세한 내용은 Oracle JDBC 사이트 등을 참고한다.
JEUS는 JDBC 4.0을 기반으로 애플리케이션에 Connection Pooling 및 기타 부가 서비스를 제공한다.
2. 데이터소스와 JDBC Connection Pooling
데이터소스는 애플리케이션에 JDBC Connection을 제공하는 Factory로 추상화된 객체로서 내부적으로 JDBC Connection Pool을 구성하여 Connection Pooling 서비스를 제공한다.
JDBC Connection Pooling은 DB로부터 일정 수의 Connection을 얻어 보관하면서 애플리케이션이 필요로 할 때 제공하고, 사용 이후의 Connection을 회수하여 재활용하는 JDBC Connection 관리 서비스다.
애플리케이션은 DB에 직접 Connection을 요청하는 것이 아니라 JNDI Lookup을 통해 DB와 연관된 데이터소스를 얻고 그것에 Connection을 요청한다. Connection 요청을 받은 데이터소스는 자신의 Connection Pool에서 Connection을 꺼내 애플리케이션에 전달함으로써 Connection 요청을 처리한다.
애플리케이션이 Connection 사용을 마치면 JEUS는 Connection을 수거하여 필요한 Connection 정리 작업을 수행하고 이후 재활용할 수 있도록 다시 Connection Pool에 넣어 관리한다.
다음은 JEUS 서버에서의 JDBC Connection Pooling 메커니즘을 간략히 표현한 그림이다.
JEUS는 boot 과정에서 Connection Pool을 생성하고 초기화하는 것이 아니라 애플리케이션으로부터 데이터소스에 대한 Connection 요청이 최초 발생할 때 Connection Pool을 생성하고 초기화한다. |
2.1. JDBC 드라이버
JDBC 드라이버는 DB와의 통신에 필요한 API들의 구현체 집합으로 JEUS는 JDBC 인증을 받은 드라이버들과 연동하여 Connection Pooling 및 기타 서비스들을 제공할 수 있다. 인증된 드라이버는 각 DB 벤더들이 홈페이지를 통해 제공하고 있다.
JEUS의 JDBC 환경 구성은 어떤 벤더의 DB를 사용하느냐에 따라 다를 수 있다. 이는 각 드라이버마다 요구하는 속성이 다르기 때문이며 따라서 조정이 필요한 세부 속성은 각 벤더의 JDBC 드라이버 매뉴얼을 확인해야 한다.
2.2. JDBC Connection Pool
JDBC Connection Pool은 DB Connection을 보다 효율적으로 사용하고 관리하기 위한 하나의 프레임워크로 실제 Connection Pooling 서비스를 제공하는 주체다.
Connection Pool 사용의 이점은 다음의 2가지로 요약할 수 있다.
-
보다 높은 성능
시스템의 성능을 향상시킬 수 있다. DB Connection 생성 및 제거는 본래 시스템에 부담을 주는 작업이므로 최초 Connection Pool에 Connection을 생성하여 채우고 이를 재활용하면 Connection Pooling 없이 Connection을 빈번히 생성하고 제거하는 경우 비롯되는 오버헤드를 크게 줄일 수 있다.
-
연결 관리
동시 Connection들의 수를 제어할 수 있다. 동시 Connection들의 수를 설정한 값 이하로 제한하여 관리함으로써 DB에 무리한 부하를 주는 문제로부터 자유로울 수 있다.
2.3. 데이터소스
데이터소스는 애플리케이션과 Connection Pool 사이의 인터페이스로 애플리케이션은 데이터소스 객체를 DB Connection의 Factory로 바라보게 된다. 데이터소스를 통한 Connection 사용 방식은 java.sql.DriverManager를 통한 Connection 사용 방식보다 많은 장점을 제공한다. 본 절에서 설명하는 데이터소스의 특성 및 기능을 잘 고려하여 그에 맞는 적절한 데이터소스를 사용하면 서비스의 성능 향상을 꾀할 수 있다.
데이터소스 타입
데이터소스는 다음의 3가지의 타입으로 분류된다.
-
기본 데이터소스
javax.sql.DataSource 타입을 의미한다. 이 타입은 Connection Pooling을 위해 사용될 수는 없는 기본 데이터소스 타입이다.
-
Connection Pool 데이터소스
javax.sql.ConnectionPoolDataSource 타입을 의미한다. JEUS는 이 타입에 대해 Connection Pool을 제공한다.
주로 다음과 같은 상황에서 사용할 수 있다.
-
XA를 사용할 필요없이 간단하게 DB에 접근하기 위한 애플리케이션을 작성하는 경우
-
Auto Commit을 false로 설정하고 직접 로컬 트랜잭션을 컨트롤하는 경우
import java.sql.Connection; Connection conn = datasource.getConnection(); conn.setAutoCommit(false); ...DB 접근 코드... // JDBC 드라이버 내부적으로 로컬 트랜잭션 진행 conn.commit();
-
XA 데이터소스
javax.sql.XADataSource 타입을 의미한다. JEUS는 이 타입에 대해 Connection Pool을 제공한다. 이 타입의 데이터소스는 Connection Pooling과 더불어 글로벌 트랜잭션(이하 XA) 연동을 지원한다.
주로 다음과 같은 상황에서 사용할 수 있다.
-
-
Servlet/EJB와 같은 Jakarta EE 컴포넌트 로직이 2개 이상의 DB로 접근해야 하는 경우
-
Jakarta EE 컴포넌트에서 하나의 DB로 접근하더라도 관련 로직들이 일련의 동작으로 묶여야 하는 경우
Connection Pool 데이터소스에 대한 XA 에뮬레이션
XA 처리 성능을 높이기 위해서 로컬 트랜잭션 최적화 기능을 사용할 수 있다. 이는 Connection Pool 데이터소스를 통해서 얻은 Connection을 XA에 참여하도록 에뮬레이션 해주는 것으로 JEUS 6에서는 로컬 트랜잭션 데이터소스라는 타입을 별도로 정의해 제공하던 기능이다. JEUS 9 에서는 로컬 트랜잭션 데이터소스 타입을 별도로 정의하지 않고 Connection Pool 데이터소스에 XA 에뮬레이션 플래그 설정을 두어 Connection Pool 데이터소스의 XA 에뮬레이션 지원 여부를 결정하게 된다.
이 기능은 주로 다음과 같은 상황에서 사용할 수 있다.
-
DB가 XA를 지원하지 않거나 JDBC 드라이버가 javax.sql.XADataSource 구현체를 제공하지 않는 경우
-
애플리케이션에서 XA가 필요하지만 성능 문제로 XA 데이터소스를 사용하고 싶지 않은 경우(즉, 로컬 트랜잭션 최적화가 필요한 경우)
최근에는 XA를 지원하지 않는 DB 또는 JDBC 드라이버는 거의 없다고 볼 수 있기 때문에 주로 로컬 트랜잭션 최적화를 위해서 사용하게 될 것이다. 그러나 반드시 염두에 두어야 할 제약 사항이 있는데, 하나의 XA에는 최대 하나의 로컬 XA 데이터소스만 참여할 수 있다는 것이다. 따라서 로컬 XA 데이터소스는 되도록 다음과 같은 상황에서 사용한다.
-
Servlet/EJB와 같은 Jakarta EE 컴포넌트 로직이 하나의 DB만 사용하기 때문에 굳이 XA 데이터소스를 사용할 필요가 없을 때
-
Jakarta EE 컴포넌트에서 여러 개의 DB를 사용하더라도 그 중 하나를 로컬 트랜잭션으로 처리해서 XA 성능을 높이고 싶을 때
여러 개의 DB를 사용하는 상황에서 주의할 점은 XA 에뮬레이션을 기능을 사용하는 Connection Pool 데이터소스는 실제로 2 Phase Commit(이하 2PC)을 지원하는 것이 아니므로 트랜잭션 복구가 제대로 되지 않을 수 있다는 것이다.
Connection Pool 데이터소스의 XA 에뮬레이션은 Auto Commit을 끄고 사용하는 로컬 트랜잭션으로 다루어지며 이는 DB 관점에서 JEUS 트랜잭션 매니저가 관리하는 XA 트랜잭션과는 서로 다른 트랜잭션이다. 대신 JEUS가 그 로컬 트랜잭션이 XA 트랜잭션에 참여할 수 있도록 에뮬레이션하므로 애플리케이션 관점에서는 하나의 트랜잭션으로 보게 된다. |
2.4. 클러스터 데이터소스
본 절에서는 클러스터 데이터소스의 장애복구 기능과 DataSource Affinity 기능, ONS와 결합기능에 대해서 설명한다.
2.4.1. 장애복구 기능
JEUS 레벨에서 RAC 인스턴스 간의 Failover 및 Failback을 지원하기 위해서 클러스터 데이터소스를 제공한다. RAC(Real Application Cluster)는 Oracle에서 제공하는 DB 클러스터링 기능이다. RAC에 관한 자세한 내용은 Oracle의 문서를 참고한다.
클러스터 데이터소스는 근본적으로는 하나의 JNDI 이름을 가진 데이터소스 인스턴스로서 복수의 개별 데이터소스들을 논리적으로 묶어 관리한다. 클러스터 데이터소스에 속한 개별 데이터소스(이하 컴포넌트 데이터소스)들 또한 각자의 JNDI 이름을 갖는 독립적인 데이터소스인데 이들은 반드시 RAC 인스턴스의 데이터소스로 설정되어야 한다. 클러스터 데이터소스는 애플리케이션으로부터 자신에게 들어온 Connection 요청을 이들 컴포넌트 데이터소스 중 하나에 위임하는 방식으로 동작한다. Connection 요청 위임은 Connection 요청 처리에 문제가 없음이 확인된 컴포넌트 데이터소스에 대해서 이루어지므로 클러스터 데이터소스는 애플리케이션에 투명하게 Failover를 수행할 수 있다.
Oracle JDBC 드라이버 레벨에서 제공하는 CTF(Connect Time Failover)보다는 JEUS의 클러스터 데이터소스를 사용하길 권장한다. Oracle CTF의 경우에는 Connection별로 Failover를 하기 때문에 데이터소스 전체가 문제가 생겼을 경우 Connection Pool에 있는 모든 Connection을 복구하려면 오랜 시간이 걸릴 수 있다. 그러나 JEUS 클러스터 데이터소스는 컴포넌트 데이터소스에 문제가 생긴 것을 감지하여 데이터소스 단위로 Failover를 수행하므로 보다 효율적이다. 더불어 JEUS 클러스터 데이터소스는 자동으로 Failback하는 기능도 제공한다.
JEUS 클러스터 데이터소스를 사용하는 방식과 Oracle JDBC 드라이버에 RAC 속성을 설정하는 방식은 그 동작이 서로 다르다. 전자는 Failover를 JEUS가 처리하는 것이기 때문에 각 RAC 인스턴스의 컴포넌트 데이터소스의 fail 여부를 감시하기 위해서 check-query와 check-query-period를 설정해야 한다. 그러나 후자는 드라이버가 Failover를 책임지므로 check-query가 필수적인 것은 아니다. 클러스터 데이터소스 설정에 관한 자세한 내용은 클러스터 데이터소스 설정을 참고한다.
2.4.2. DataSource Affinity 기능
글로벌 트랜잭션이 RAC에서 이루어지게 되는 경우에는 물리적으로 분산된 서로 다른 RAC 인스턴스들에서 트랜잭션 처리가 되는 것보다 되도록이면 하나의 RAC 인스턴스에 한정되어 트랜잭션 처리가 되는 것이 성능상 유리하다. 또한 XA Emulation을 설정한 ConnectionPoolDataSource를 멤버 데이터소스로 갖는 클러스터 데이터소스를 사용하여 강제로 로컬 트랜잭션을 RAC에서 처리하는 경우에는 반드시 하나의 RAC 인스턴스만 사용할 필요가 생긴다.
글로벌 또는 로컬 트랜잭션 처리 상황에서 클러스터 데이터소스는 최초의 커넥션 요청이 어떤 컴포넌트 데이터소스 및 연관된 RAC 인스턴스에서 처리되었는지 기억하고 이후의 커넥션 요청은 무조건 해당 컴포넌트 데이터소스로 위임함으로써 DataSource Affinity, 즉 하나의 RAC 인스턴스에 한정되어 글로벌 또는 로컬 트랜잭션이 처리됨을 보장한다.
복수의 클러스터 데이터소스가 동일한 RAC를 바라보고 있는 경우에도 각각의 클러스터 데이터소스로의 커넥션 요청은 서로 다른 클러스터 데이터소스에 대한 커넥션 요청이라고 할지라도 동일한 RAC 인스턴스에서 처리되도록 한다. 또한 만약 복수의 RAC가 연관되어 있다면 각각의 RAC에 대해서도 역시나 DataSource Affinity가 보장된다. 가령 서로 다른 클러스터 데이터소스 a와 클러스터 데이터소스 b가 각각 서로 다른 RAC A와 RAC B를 바라보고 있다면 클러스터 데이터소스 a로의 커넥션 요청은 RAC A에서 DataSource Affinity를 보장하고 클러스터 데이터소스 b로의 커넥션 요청은 RAC B에서 DataSource Affinity를 보장한다. 서로 다른 RAC인 RAC A와 RAC B 간에는 DataSource Affinity를 보장하는 것이 근본적으로 불가능함에 유의하기 바란다.
DataSource Affinity가 설정되어 있을 경우 기존의 Failover, Failback, Loadbalancing 방식은 무시되고 트랜잭션에 묶인 RAC 인스턴스와 동일한 데이터소스를 우선 선택한다. 트랜잭션 하에서 선택할 데이터소스가 존재하지 않을시 기존의 위 정책들로 데이터소스를 선택하게 된다.
2.4.3. ONS와 결합된 클러스터 데이터소스
ONS는 RAC node 간 서로의 상태 정보 공유를 가능하게끔 하는 Oracle의 Notification Service다. RAC에 ONS가 설정되어 있으면 기본적으로 RAC 노드들은 각자의 상태를 모든 RAC 노드들과 공유하게 된다. 한편 RAC 서버 컴포넌트가 아니더라도 ONS 클라이언트로써 ONS에 참여하면 ONS로부터 RAC 노드 상태 정보들을 일부 얻을 수 있는데 JEUS는 이를 이용하여 ONS와 결합된 보다 향상된 기능의 클러스터 데이터소스를 제공한다. ONS와 결합된 클러스터 데이터소스는 내부적으로 각 컴포넌트 데이터소스와 연관된 RAC 인스턴스를 매핑하고 있다. 이와 같은 구조는 ONS로부터 얻은 RAC 인스턴스 정보를 연관된 컴포넌트 데이터소스 관리에 이용하는 것을 가능케 한다.
JEUS가 ONS 클라이언트로써 ONS로부터 얻을 수 있는 상태 정보는 크게 두 가지다.
-
RAC 인스턴스 Up & Down Notification
RAC 인스턴스가 기동했는지 혹은 종료했는지 알려준다.
-
RAC 인스턴스별 가용량 Percentage
Runtime Load Balancing Advisory라고도 불리는 이 정보는 RAC 전체의 가용량을 100으로 하여 RAC 인스턴스별 가용량을 Percentage로 알려준다.
ONS와 결합된 클러스터 데이터소스 기능
다음은 ONS와 결합된 클러스터 데이터소스에서 제공하는 기능에 대한 설명이다.
-
보다 효과적인 컴포넌트 데이터소스 상태 관리
DB의 상태를 파악하기 위한 기존 방식은 Polling이었는데 이는 요청 처리 와중에 수행됨으로 인해 성능상 부담이 되거나 네트워크 단절 상황에서는 DB 상태 파악이 되지 않는 문제가 있었다. RAC 인스턴스 Up & Down Notification을 이용하게 되면서는 그러한 문제를 피하면서 컴포넌트 데이터소스의 실패 및 복구 여부를 보다 효과적으로 감지할 수 있게 되었다.
-
Runtime Load Balancing Advisory를 이용한 효율적인 Load Balancing
기존에는 DB의 가용량을 판단할 수 없었으므로 단순한 Round-Robin 방식의 Load Balancing만을 제공할 수밖에 없었다. 그러나 이제는 Runtime Load Balancing Advisory를 통해 실시간으로 RAC 인스턴스 별 상대적 가용량을 알 수 있게 됨으로써 그를 바탕으로 한 효율적인 Load Balancing이 가능해졌다. 가령 컴포넌트 데이터소스 A와 컴포넌트 데이터소스 B가 각각 RAC 인스턴스 A와 RAC 인스턴스 B와 연관되어 있으며 이들의 가용량이 각각 Runtime Load Balancing Advisory를 통해 60%, 40%로 알려지면 이후의 커넥션 요청은 3:2의 비율로 컴포넌트 데이터소스 A와 컴포넌트 데이터소스 B로 위임된다.
ONS 설정
JEUS를 ONS 클라이언트로 기능하게 하기 위해서는 우선 ONS 라이브러리를 설치해야 한다.
Oracle 지원 사이트에서 ons.jar를 다운로드 받아 JEUS_HOME/lib/datasources 디렉터리에 두면 된다. 이제 클러스터 데이터소스에 ONS 관련 설정을 함으로써 ONS와 결합된 클러스터 데이터소스를 사용할 수 있다. 먼저 기본적으로 ONS상의 각 RAC 노드들이 ONS 통신에 사용하는 IP, 포트를 설정해야 한다. 여기까지 설정하면 클러스터 데이터소스는 ONS와 결합된다. 이제 Failover-Failback 방식이든 Load Balancing 방식이든 클러스터 데이터소스는 컴포넌트 데이터소스의 실패 및 복구 여부를 ONS를 통하여 보다 효과적으로 감지할 수 있다. 특히나 Load Balancing 방식일 때는 Runtime Load Balancing Advisory를 이용하여 좀 더 효율적인 Load Balancing을 제공하게 된다.
3. 데이터소스 및 Connection Pool 관리
JEUS가 도메인 구조로 확장됨에 따라 데이터소스 및 Connection Pool 관리 구조에도 일부 변화가 생겼다. 그러나 확장된 도메인 구조에 대한 이해가 바탕이 되면 변화된 데이터소스 및 Connection Pool 관리 구조에 대한 학습은 크게 어렵지 않은 수준에서 이루어질 수 있다.
JEUS에서 서비스를 수행하는 최소 단위는 서버이며 경우에 따라 복수의 서버가 클러스터로 묶여 서비스를 수행할 수도 있다. 다시 이들 서버 및 클러스터는 하나의 관리 단위로 묶여질 수 있는데 그러한 관리 단위가 바로 도메인이다. 즉, 도메인은 연관되어 관리될 필요가 있는 서버 및 클러스터들의 집합을 의미한다. 도메인에는 도메인에 속한 서버 및 클러스터들을 관리하고 그와 관련된 제반 서비스를 제공하는 특별한 역할의 유일한 서버가 존재하는데 이를 MASTER라고 한다. MASTER를 제외한 도메인에 속한 모든 서버는 MS라고 한다. MASTER는 MASTER로 기능하는 동시에 MS로도 기능할 수 있으나 서비스는 MS를 통해 제공하고 MASTER는 본연의 도메인 관리 역할만 수행하는 방식으로 사용할 것을 권장한다. JEUS의 도메인 구조에 대한 보다 자세한 내용은 JEUS Domain 안내서를 참고한다.
본 절에서는 도메인 구조에서 데이터소스 및 Connection Pool이 관리되는 방식에 대해서 설명한다.
데이터소스는 기본적으로 도메인 범주에서 노출되는 자원이다. 도메인에 속한 서버 및 클러스터(보다 정확히 얘기하면 클러스터에 속한 서버)가 노출된 데이터소스 설정을 참조하여 자신들만의 Connection Pool을 생성해 Connection Pool 서비스를 제공하게 되는 것이다. 클러스터는 서버들의 묶음을 추상화한 것일 뿐 서비스를 제공하는 실질적 주체는 아니므로 클러스터에서 참조하는 데이터소스는 실제로는 그것에 속한 서버들에서 유효하다. 그렇기 때문에 클러스터에 속한 서버들은 클러스터에서 참조하는 데이터소스를 참조할 수 있다. 또한 클러스터에 속한 서버는 자체적으로 데이터소스를 참조하도록 설정될 수 있다. 이 경우 서버는 클러스터에서 참조하는 데이터소스와 자신이 참조하는 데이터소스 모두를 유효한 데이터소스로 사용할 수 있게 된다.
서버 및 클러스터의 데이터소스 참조는 서버 및 클러스터 자신이 참조할 데이터소스의 ID를 명시하여 등록함으로 가능해진다. 즉, 서버 및 클러스터가 특정 데이터소스 ID를 명시하면 해당 서버 및 해당 클러스터에 속한 서버는 명시한 데이터소스의 설정을 읽어 Connection Pool을 생성하는 데 필요한 정보들을 구성하고 그것을 데이터소스의 JNDI 이름과 매핑하여 자신의 JNDI Repository에 bind한다. 이 과정이 이루어지고 나면 서버에 deploy된 애플리케이션은 bind한 JNDI 이름으로 데이터소스를 lookup하여 Connection Pool을 생성하고 사용할 수 있게 된다.
데이터소스의 JNDI bind는 서버 단위로 이루어지므로 서로 다른 데이터소스라할지라도 동일한 서버에 JNDI bind되지 않음을 보장할 수 있으면 동일한 JNDI 이름을 가질 수 있다. 이는 곧 동일한 JNDI 이름을 가진 서로 다른 데이터소스들을 임의의 서버에서 동시에 참조하도록 하는 설정은 허용되지 않음을 의미한다. 도메인에서 데이터소스 ID로서 데이터소스를 구별하는 이유는 이처럼 서로 다른 데이터소스가 동일한 JNDI 이름을 가질 수 있기 때문이다. 데이터소스 ID는 도메인에서 유일한 값으로 설정되어 데이터소스의 식별자로서 기능할 수 있어야 한다. |
다음은 좀 더 구체적인 예로 MASTER와 3개의 MS로 이루어진 도메인 구성이다.
MS1은 클러스터 데이터소스를 등록하고 있다. 클러스터 데이터소스의 컴포넌트 데이터소스는 DS1과 DS2로서 MS1이 클러스터 데이터소스를 온전히 사용하기 위해서는 클러스터 데이터소스의 컴포넌트 데이터소스인 DS1과 DS2 역시 MS1에 등록되어야 한다. 이와 같이 설정함으로 MS1은 DS1과 DS2 Connection Pool을 각각 생성한 후 클러스터로 묶어 클러스터 Connection Pool 서비스를 제공할 수 있다.
한편 MS2와 MS3는 클러스터로 묶여있다. 클러스터는 DS3를 등록하고 있으므로 DS3는 클러스터에 속한 MS2와 MS3에서 모두 유효하다. 이는 곧 MS2와 MS3 각각이 DS3 Connection Pool을 생성해 Connection Pool 서비스를 제공할 수 있음을 의미한다.
또한 MS3는 단독으로 자신에 DS4를 등록하고 있다. 따라서 MS3는 클러스터에서 등록한 DS3와 더불어 자신이 등록한 DS4에 대해서도 Connection Pool 서비스를 제공할 수 있다.
각각의 MS는 서버 수준에서의 데이터소스 및 Connection pool 관리 서비스를, MASTER는 도메인 수준에서의 데이터소스 및 Connection Pool 관리 서비스를 수행한다. MASTER 서비스는 각각의 MS 서비스들과 연계하여 도메인에 존재하는 모든 데이터소스 및 Connection Pool을 총체적으로 관리하며 콘솔 툴부터 데이터소스 및 Connection Pool 관련 요청을 처리하게 된다.
4. 데이터소스 설정
데이터소스 및 JDBC Connection Pool을 실제 JEUS에서 사용하기 위해 가장 먼저 해야할 일은 JEUS_HOME/lib/datasource/ 디렉터리 내에 JDBC 드라이버 라이브러리가 존재하는지 확인하고 데이터소스 구성에 필요한 정보를 설정하는 것이다. 데이터소스 설정은 크게 JDBC 드라이버 setup 등에 필요한 기본 설정과 Connection Pool 설정으로 이루어진다.
본 절에서는 콘솔 툴을 사용한 설정 방법에 대해서 간단히 설명한다. 콘솔 툴을 사용한 자세한 설정 방법은 JEUS Reference 안내서의 add-data-source를 참고한다.
[MASTER]domain1.adminServer>add-data-source -id ds1 -dst ConnectionPoolDataSource -dscn oracle.jdbc.pool.OracleConnectionPoolDataSource -sn 61.77.153.4 -pn 1521 -dn orcl -user scott -password tiger --property driverType:java.lang.String=thin Successfully performed the ADD operation for data source [ds1] to domain. Check the results using "add-data-source". [MASTER]domain1.adminServer>addds Shows the current configuration. Data sources in domain ==================================================================== +------+-----------------------------------------------------------+ | ds1 | common data source | +------+-----------------------------------------------------------+ ==================================================================== [MASTER]domain1.adminServer>
DataSourceAccountProvider 인터페이스
JEUS는 기본적으로 데이터소스에 DB 접속 계정 정보를 설정할 수 있게 하여, JEUS 내 설정 저장소에 보관함으로써 사용자 어플리케이션에서 JDBC connection 요청시 매번 파라미터로 DB 접속 계정 정보를 전달하지 않아도 되게끔 하고있다. 또한 이렇게 사용자가 저장하는 DB 접속 계정 정보는 안전한 관리를 위해 JEUS Security와 연동하여 암호화 과정을 거친 후 저장소에 보관하는 것이 가능하다.
이 외에도, JEUS는 데이터소스에서 사용할 DB 접속 계정 정보를 JEUS 설정이 아닌 외부 저장소에 보관할 수도 있도록 지원하며, DB 접속 계정을 보호하기 위한 보안 모듈 또한 JEUS Security 외에도 다른 외부 보안 모듈을 사용할 수 있도록 지원한다. 이와 같은 외부 시스템과의 유연한 연동을 위해 JEUS는 jeus.jdbc.helper.DataSourceAccountProvider 인터페이스를 명시하고 있다. 사용자는 자신이 원하는 외부 시스템과 연동하도록 이 인터페이스를 적절히 구현함으로써 다양하고 자유로운 방식으로 DB 접속 계정 정보를 관리할 수 있다.
jeus.jdbc.helper.DataSourceAccountProvider 인터페이스의 명세는 다음과 같다.
public interface DataSourceAccountProvider { String getUser(Map<String, String> dataSourceConfigurationMap) throws DataSourceAccountProviderException; String getPassword(Map<String, String> dataSourceConfigurationMap) throws DataSourceAccountProviderException; }
메소드 | 설명 |
---|---|
getUser(Map<String, String> dataSourceConfigurationMap) |
JEUS로부터 파라미터로 데이터소스 설정이 담긴 Map을 넘겨받아 필요시 이를 적절히 활용하여 JEUS에게 DB 접속을 위한 평문 user 값을 리턴해준다. |
getPassword(Map<String, String> dataSourceConfigurationMap) |
JEUS로부터 파라미터로 데이터소스 설정이 담긴 Map을 넘겨받아 필요시 이를 적절히 활용하여 JEUS에게 DB 접속을 위한 평문 password 값을 리턴해준다. |
앞서 소개한 jeus.jdbc.helper.DataSourceAccountProvider 인터페이스의 각 API에 파라미터로 전달되는 Map에는 JEUS 데이터소스 설정값 중 일부가 들어가며, 구현체에서는 다음과 같은 key 값으로 해당되는 value를 얻을 수 있다.
key | value |
---|---|
DATA_SOURCE_ID |
JEUS 데이터소스 설정에 입력된 Data Source ID |
EXPORT_NAME |
JEUS 데이터소스 설정에 입력된 Export Name |
VENDOR |
JEUS 데이터소스 설정에 입력된 Vendor |
DATA_SOURCE_CLASS_NAME |
JEUS 데이터소스 설정에 입력된 Data Source Class Name |
SERVER_NAME |
JEUS 데이터소스 설정에 입력된 Server Name |
PORT_NUMBER |
JEUS 데이터소스 설정에 입력된 Port Number |
DATABASE_NAME |
JEUS 데이터소스 설정에 입력된 Database Name |
USER |
JEUS 데이터소스 설정에 입력된 User |
PASSWORD |
JEUS 데이터소스 설정에 입력된 Password |
앞서 소개한 jeus.jdbc.helper.DataSourceAccountProvider 인터페이스의 각 API가 던지는 DataSourceAccountProviderException은 다음과 같은 상황에서 발생해야 한다.
Exception 이름 | Exception이 발생하는 상황 |
---|---|
jeus.jdbc.datasource.DataSourceAccountProviderException |
DB에 접속하기 위해 필요한 평문 user 또는 password 값을 얻는데 실패하였을 때 발생 |
끝으로, 사용자의 의도대로 구현된 jeus.jdbc.helper.DataSourceAccountProvider 인터페이스 구현체를 사용하기 위해서는 그 클래스 이름을 다음 jvm-option으로 JEUS 서버에 지정해 주어야 한다.
jvm-option 이름 | jvm-option 값 |
---|---|
jeus.jdbc.config.data-source-account-provider-class-name |
jeus.jdbc.helper.DataSourceAccountProvider 인터페이스에 대한 구현체의 전체 이름 |
만약에 사용자가 위의 jvm-option을 설정하지 않는다면, JEUS는 JEUS Security와 연동하는 기본 구현체를 사용한다.
위의 명세를 바탕으로 다음과 같이 Customize 된 DataSourceAccountProvider 구현이 가능하다. 아래 예시들에서는 DB 접속 계정 정보를 scott/tiger라고 가정한다.
public class MyDataSourceAccountProvider implements DataSourceAccountProvider { @Override public String getUser(Map<String, String> dataSourceConfigurationMap) throws DataSourceAccountProviderException { // JEUS 설정에서 넘겨받은 user 값을 그대로 다시 리턴. return dataSourceConfigurationMap.get(USER); // scott이 얻어짐. } @Override public String getPassword(Map<String, String> dataSourceConfigurationMap) throws DataSourceAccountProviderException { // JEUS 설정에서 넘겨받은 password 값을 그대로 다시 리턴. return dataSourceConfigurationMap.get(PASSWORD); // tiger가 얻어짐. } }
public class MyDataSourceAccountProvider implements DataSourceAccountProvider { @Override public String getUser(Map<String, String> dataSourceConfigurationMap) throws DataSourceAccountProviderException { // JEUS 설정에서 넘겨받은 SERVER_NAME 값을 이용해서 파일에서 적절한 파싱을 통해 user를 얻어옴. File file = getFile(); // DB 접속 계정 정보가 적힌 파일을 얻어옴. // 파일을 잘 파싱해서 user 값인 scott을 얻어오도록 자체적으로 구현. return getUserFromFileWithSID(file, dataSourceConfigurationMap.get(SERVER_NAME)); } @Override public String getPassword(Map<String, String> dataSourceConfigurationMap) throws DataSourceAccountProviderException { // JEUS 설정에서 넘겨받은 SERVER_NAME 값을 이용해서 파일에서 적절한 파싱을 통해 password를 얻어옴. File file = getFile(); // DB 접속 계정 정보가 적힌 파일을 얻어옴. // 파일을 잘 파싱해서 password 값인 tiger를 얻어오도록 자체적으로 구현. return getPasswordFromFileWithSID(file, dataSourceConfigurationMap.get(SERVER_NAME)); } }
public class MyDataSourceAccountProvider implements DataSourceAccountProvider { @Override public String getUser(Map<String, String> dataSourceConfigurationMap) throws DataSourceAccountProviderException { // JEUS 설정에서 넘겨받은 user 값을 그대로 다시 리턴. return dataSourceConfigurationMap.get(USER); // scott이 얻어짐. } @Override public String getPassword(Map<String, String> dataSourceConfigurationMap) throws DataSourceAccountProviderException { // 외부 보안 모듈인 ExternalSecurity에 파라미터로 전달할 JEUS 데이터소스 설정 값들을 얻음. // JEUS 데이터소스 설정상의 data source ID를 얻음. String dataSourceID = dataSourceConfigurationMap.get(DATA_SOURCE_ID); // JEUS 데이터소스 설정상의 server name을 얻음. String serverName = dataSourceConfigurationMap.get(SERVER_NAME); // JEUS 데이터소스 설정상의 user를 얻음. String user = dataSourceConfigurationMap.get(USER); // 외부 보안 모듈인 ExternalSecurity에 파라미터로 dataSourceID, serverName, //user를 전달하고, ExternalSecurity에서는 그에 맞는 password를 리턴해준다고 가정. return ExternalSecurity.getPassword(dataSourceID, serverName, user); // tiger가 얻어짐. } }
4.1. Connection Pool 설정
jeusadmin에서 list-data-sources 명령어로 현재 datasource 설정을 확인할 수 있다.
[MASTER]domain1.adminServer>list-data-sources -id ds1 The configuration of the data source [ds1] ================================================================================ +----------------------------+-------------------------------------------------+ | Configuration Name | Configuration Value | +----------------------------+-------------------------------------------------+ | id | ds1 | | export-name | ds1 | | data-source-class-name | oracle.jdbc.pool.OracleConnectionPoolDataSource | | data-source-type | ConnectionPoolDataSource | | server-name | 61.77.153.4 | | port-number | 1521 | | database-name | orcl | | user | scott | | password | tiger | | login-timeout | 0 | | auto-commit | DRIVER | | stmt-query-timeout | 0 | | pool-destroy-timeout | 10000 | | property | [driverType;java.lang.String;thin] | | support-xa-emulation | false | | min | 2 | | max | 30 | | step | 1 | | period | 3600000 | | enable-wait | false | | wait-time | 10000 | | max-use-count | 0 | | dbaTimeout | -1 | | stmt-caching-size | -1 | | stmt-fetch-size | -1 | | connection-trace | false | | get-connection-trace | true | | auto-commit-trace | false | | use-sql-trace | false | | keep-connection-handle-open| false | +----------------------------+-------------------------------------------------+ ================================================================================ [MASTER]domain1.adminServer>
다음은 각 설정 항목에 대한 설명이다.
-
Pooling
JDBC Connection Pool의 사이즈 및 그의 조정에 관련된 설정들을 정의한다.
항목 설명 Min
Connection Pool에 Pooling되는 Connection의 최솟값을 지정한다.
Max
Connection Pool에 Pooling되는 Connection의 최댓값을 지정한다.
Step
Connection Pool에 Connection이 부족할 때 현재 Connection의 개수가 최댓값 이하인 경우 DB로부터 Connection을 새로 받아와 채우는데 이때 새로 받아오는 Connection의 개수를 지정한다.
Period
Connection Pool의 크기를 최솟값에 맞춰 조정하는 주기를 설정한다.
Connection Pool의 크기가 최솟값을 초과하는 경우에는 사용하지 않는 Connection들을 닫아주고 Connection Pool의 크기가 최솟값에 미치지 못하는 경우에는 DB로부터 Connection을 새로 받아와 채운다. (단위: ms)
-
Wait Free Connection
Connection Pool에 있는 모든 Connection들이 점유되어 있을 때 Connection 요청을 핸들링하는 메소드를 정의한다.
항목 설명 Enable Wait
Connection Pool에 사용 가능한 Connection이 없고 Connection도 더 이상 늘릴 수 없을 때 Connection 요청을 처리하는 방법을 결정한다.
-
true : 이용 가능한 Connection을 얻기 위해 기다린다.
-
false : 새로운 Connection을 만들어서 제공하지만 그 Connection은 반환되었을 때 Pooling되지 않고 버려진다. 이를 일회용(disposable) Connection이라고도 한다.
Wait Time
'Enable Wait'이 true인 경우에만 유효한 설정으로 Connection을 얻기 위해 대기하는 한계 시간을 나타낸다. 만약 이 시간이 지나도 Connection을 얻지 못하면 JEUS는 타임아웃 예외를 발생시킨다. (단위: ms)
-
-
Connection Validation
애플리케이션이 Connection을 요청했을 때 Connection을 애플리케이션에 넘겨주기 전 특정 쿼리를 수행하여 Connection의 상태를 점검(validation)하는 기능이다. JDBC Connection 내부 에러로 인한 끊김, 방화벽에 의한 소켓 끊김 현상 등을 체크할 때 유용하다.
Connection의 상태에 이상이 있는 경우 Connection을 DB로부터 새로 받아 애플리케이션에 전달한다. 만약 RAC를 위한 클러스터 데이터소스에 속한 데이터소스라면 반드시 이 설정을 해야 한다.
항목 설명 Check Query
Connection 상태 점검에 사용될 쿼리를 설정한다. 보통 DB와의 연결 유효성만을 확인하면 되므로 간단한 select 쿼리를 사용하는 것을 권장한다.
한편 JEUS 7 Fix#2부터는 DB와의 연결 유효성을 확인할 때 check-query를 수행하는 대신 JDK1.6에서 java.sql.Connection에 추가된 isValid 메소드를 이용할 수 있다. 쿼리문 대신 "use isValid method"를 적으면 된다.
그 밖의 Connection Validation 관련 설정들(Check Query Timeout, Check Query Period 등)은 isValid 메소드를 사용할 때도 동일하게 적용된다.
Check Query Timeout
Connection 점검을 위해 Check Query를 수행했을 때 DB가 응답이 없어 드라이버가 계속 기다리는 상황이 발생할 수 있다. 이런 경우를 피하기 위해 Check Query에 대해 쿼리 타임아웃을 적용한다. (단위: ms)
이것은 JDBC API에서 정의한 java.sql.Statement#setQueryTimeout 메소드를 호출함으로 가능하다.
1000ms보다 적을 경우 0으로 설정되므로 주의한다.
Non Validation Interval
Connection 점검이 너무 잦아서 오버헤드가 발생하는 경우 설정한다. Connection 점검을 수행하기 직전의 시각과 가장 최근의 Connection 점검 시각과의 차이가 설정한 시간 간격 이내면 Connection 점검을 생략하도록 하는 설정이다. (단위: ms)
예를 들어 이 설정값이 5000ms인 경우 어떤 Connection의 마지막 Connection 점검 시간으로부터 아직 5초가 지나지 않았다면 그 Connection에 대한 점검이 생략된 채 애플리케이션에 전달된다.
Check Query Period
Connection Pool의 Connection들을 설정한 주기마다 체크하여 문제가 있는 Connection을 제거한다. 클러스터 데이터소스에 속한 데이터소스는 자신의 상태 체크에 사용하므로 반드시 설정해야 한다. (단위: ms)
Check Query Class
사용자나 개발자가 Connection 점검 기능을 Customize하고 싶을때 그것을 위해 구현한 클래스의 패키지 이름을 포함한 이름을 적어준다.
이때 그 클래스는 반드시 jeus.jdbc.connectionpool.JEUSConnectionChecker 인터페이스를 구현해야 한다. 자세한 내용은 "JEUSConnectionChecker 인터페이스"를 참고한다.
Check Query Retrial Count
Connection 점검은 기본적으로 Destroy Policy On Check Query가 FAILED_CONNECTION_ONLY로 설정되어 있을 경우 한 번 수행된다.
Destroy Policy On Check Query가 ALL_CONNECTIONS로 설정되어 있을 경우에는 최초의 Connection 점검에서 Connection 이상이 확인되면 또 다른 Connection에 대해서 한 번 더 Connection 점검이 이루어져 총 두 번의 Connection 점검이 수행될 수 있다. 이 설정값이 이러한 기본 Connection 점검 수행 횟수에 더해져 최종 Connection 점검 수행 횟수가 정해진다.
Destroy Policy On Check Query
Connection이 유효하지 않은 것으로 확인되었을 때 Connection Pool에 있는 다른 Connection들에 대한 처리 정책을 설정한다.
-
FAILED_CONNECTION_ONLY : 유효하지 않은 것으로 확인된 Connection만 제거한다.
-
ALL_CONNTECTIONS : 유효하지 않은 것으로 확인된 Connection을 제거하고 Connection Pool에 있는 다른 Connection의 유효성을 한 번 더 확인한다. 그조차 유효하지 않은 것으로 확인되면 Connection Pool의 모든 Connection을 제거한다.
-
-
Connection Pool
기타 Connection Pool의 부가 기능들을 설정한다.
항목 설명 Delegation Datasource
트랜잭션과 연동하지 않은 상태에서는 XA 데이터소스를 통해 Connection을 얻기보다 Connection Pool 데이터소스를 통해 Connection을 얻는 것이 낫다.
기능상 차이가 없을 뿐더러 트랜잭션 연동을 위한 기능을 포함하고 있는 XA Connection은 아무래도 시스템에 부담을 더 주기 때문이다. 이를 위해 XA 데이터소스인 경우 이 설정을 통하여 트랜잭션과 연동하지 않은 상태에서의 Connection 요청을 위임할 Connection Pool 데이터소스를 지정한다.
한편 Oracle, DB2 등에서 XA Connection을 트랜잭션 없이 사용도 하고 트랜잭션에 연동도 하면서 사용하다 보면 XA를 시작할 수 없는 예외가 발생하기도 하는데 정확한 원인은 알 수 없기 때문에 이를 회피하기 위한 방편으로서도 이 설정을 이용한다.
Max Use Count
Connection의 최대 사용 횟수이다. 이 사용 회수 이상이 되면 새로운 Connection으로 교체한다. (기본값: 0, Connection을 교체하지 않겠다는 의미)
Delegation Dba
DB의 세션을 강제로 죽일 수 있는 권한(DBA 권한)을 가진 데이터소스(이하 DBA 위임 데이터소스)의 JNDI 이름을 설정한다. 이 설정을 한 데이터소스로부터 얻어진 Connection을 이용한 쿼리 수행이 일정 시간 이상 지체되면 JEUS는 위임 DBA 데이터소스를 통해 해당 Connection과 연관된 DB 세션을 강제로 제거하도록 하는 쿼리를 DB에 날린다.
이후 애플리케이션이 사용 불가능해진 Connection으로 인해 발생한 예외를 처리하고 Connection을 닫아주게 되면 JEUS는 그 Connection을 제거하고 DB로부터 새로운 Connection을 얻어 Connection Pool에 넣는다. 현재 Tibero, Oracle, Sybase에 대해서 이 기능을 지원한다.
이 기능은 JDBC 2.0 이하 JDBC 드라이버에서 쿼리 수행이 지나치게 오래 걸릴 때 그것을 중단시킬 방법으로서 고안된 것이다. 그러나 JDBC 3.0 또는 그 이상의 버전을 구현한 JDBC 드라이버는 java.sql.Statement#setQueryTimeout을 구현하므로 이 기능을 통해 강제로 DB 세션을 제거하기보다는 Stmt Query Timeout 설정을 이용하는 것을 권장한다.
특히나 XA 데이터소스의 경우 XA가 정상적으로 진행하는 도중에 DB 세션이 제거되면 XA 처리에 문제가 발생할 수 있기 때문에 Stmt Query Timeout 설정과 서버의 트랜잭션 타임아웃 설정을 적절하게 사용하도록 한다.
Dba Timeout
위임 DAB 데이터소스는 이 설정으로 지정한 시간 동안만 Connection의 쿼리 수행을 기다려준다. 설정한 시간이 경과하면 해당 Connection과 연관된 DB 세션을 강제로 제거하도록 하는 쿼리를 DB로 날린다. (단위: ms)
Delegation DBA가 설정된 경우에만 유효하다.
Stmt Caching Size
JDBC 드라이버는 애플리케이션에서 PreparedStatement를 요청할 때마다 파라미터로 넘어온 SQL 문장을 파싱하게 된다. 이 파싱 작업이 성능에 영향을 줄 수 있기 때문에 이를 피하기 위해서 JEUS 내부적으로 PreparedStatement를 캐시하는 기능을 제공한다. 이 설정은 캐싱할 PreparedStatement의 개수를 지정한다.
Stmt Fetch Size
JDBC 드라이버 Statement의 fetch 사이즈를 설정한다.
Use Sql Trace
Connection별로 사용하고 있는 SQL 쿼리를 보여주는 기능이다. jeus.jdbc.sql 로거의 레벨을 FINE으로 설정할 경우 서버 로그를 통해서 SQL 쿼리 히스토리를 확인할 수 있다.
이 기능을 사용할 경우 JDBC 드라이버의 Statement 구현체를 JEUS의 Statement 구현체로 감싸게되므로 JDBC 드라이버의 Statement 객체를 캐스팅해서 사용하는 애플리케이션은 이 기능을 사용할 수 없다.
Keep Connection Handle Open
Connection을 Pooling하는 동안 Connection 핸들(또는 논리적 Connection)을 항상 열어두고 사용할 때 설정한다.
[참고]
-
IBM DB2에서 제공하는 Universal Driver(JCC) type 4의 XA 데이터소스를 사용할 경우 이 기능을 사용할 것을 권장한다. 여러 Thread들이 서로 다른 물리적 Connection에 대한 Connection 핸들을 open & close하면서 사용하다가 hang up되는 문제가 발생하기 때문이다.
이들 Thread들은 내부적으로 같은 vector(java.util.Vector)를 공유해서 사용하고 있는데 한 Thread가 vector에 대한 락을 선점한 상태에서 무한루프에 빠지고 다른 Thread들은 그 lock을 기다리게 되는 것이 표면적 원인이다. DB2 내부 로직을 알 수 없기에 보다 근본적인 원인은 알 수 없지만 테스트 결과 Connection 핸들을 항상 열어두면 문제가 발생하지 않는 것을 확인하였다. Connection 핸들을 항상 열어두면 내부 공유 vector에 접근하는 일이 Connection 핸들을 가장 처음 생성할 때와 물리적 Connection을 닫을 때 외에는 없기 때문이다.
-
DB2 드라이버 3.53.95부터 위의 버그가 해결되었다. 이에 대한 IBM 공식 버그 리포트 넘버는 APAR IZ41181이며 DB2 9.5 Fixpak 4 문서에서 확인할 수 있다.
[주의]
이 기능을 사용하면 Connection 핸들이 닫히지 않으므로 Connection을 닫을 때 드라이버가 해주는 클리어 작업이 이뤄지지 않는다. 예를 들어 Oracle JDBC 드라이버의 경우 Auto Commit을 false로 해놓고 사용하다가 commit이나 rollback을 하지 않고 Connection을 닫으면 무조건 commit을 하도록 되어 있는데 이러한 처리가 되지 않는다.
Init Sql
Connection을 생성한 후 가장 처음으로 수행할 SQL 쿼리를 설정한다.
-
-
Connection Trace
Connection 관련 부가 정보 제공 여부를 결정한다.
항목 설명 Enabled
Connection 관련 부가 정보 제공 여부를 결정한다.
-
false : 'Get Connection Trace'와 'Auto Commit Trace' 설정이 모두 무효하다.
Get Connection Trace
애플리케이션이 java.sql.DataSource#getConnection을 호출했을 때의 Stack Trace를 확인할 수 있도록 한다.
Auto Commit Trace
java.sql.Connection#setAutoCommit이 호출되었을 때 관련 로그와 Stack Trace를 서버 로그에 기록하도록 한다. 단, jeus.jdbc.connection-trace 로거의 로그 레벨을 FINE으로 설정해야 한다.
-
JEUSConnectionChecker 인터페이스
Check Query Class 설정에서 언급한 jeus.jdbc.connectionpool.JEUSConnectionChecker 인터페이스의 명세는 다음과 같다. Customize된 check-query 기능을 사용하기 원할 경우 이 인터페이스를 구현하고 해당 클래스를 Check Query Class로서 설정한다.
public interface JEUSConnectionChecker { void setConnectionPoolID(String connectionPoolID); void setQueryString(String query); void setQueryTimeout(int timeout); void checkConnection(Connection vcon) throws SQLException; }
메소드 | 설명 |
---|---|
setConnectionPoolID() |
데이터소스 ID 설정값이 인자로 호출된다. 정보성 자료로 활용할 수 있다. |
setQueryString() |
Check Query가 설정된 경우 설정값이 인자로 호출된다. 설정한 쿼리가 커넥션 점검에 사용된다. |
setQueryTimeout() |
Check Query Timeout이 설정된 경우 설정값이 인자로 호출된다. 설정한 쿼리 타임아웃이 커넥션 점검에 적용된다. |
checkConnection() |
실제 Connection 점검을 수행할 때 불려진다. 그러므로 개발자는 이 메소드에 자신이 커넥션을 점검할 때 수행할 작업들을 구현한다. |
JEUS는 JEUSConnectionChecker 인터페이스에 대한 구현체로 jeus.jdbc.connectionpool.DefaultConnectionChecker와 jeus.jdbc.connectionpool.TimeLimitedConnectionChecker 두 가지를 기본적으로 제공한다.
사용자가 Check Query Class에 별도의 설정을 하지 않았을 경우 가장 기본적인 구현체인 DefaultConnectionChecker가 자동으로 설정되어 동작하고, 사용자가 TimeLimitedConnectionChecker를 설정하였다면 JDBC 드라이버 뿐만 아니라 JEUS 자체적으로도 Check Query Timeout을 처리하는 방식으로 Connection Validation이 동작하게 된다. 이렇게 TimeLimitedConnectionChecker를 사용하는 경우에는 JDBC 드라이버가 쿼리 수행 중 hang에 빠진 경우에도 JEUS가 Connection Validation을 계속 이어나갈 수 있지만, 좀비 스레드가 생성될 수 있으므로 문제 상황을 로그로 확인할 수 있도록 하기 위해 jeus.connectionpool.time-limited-connection-checker 로거의 레벨을 최소 FINE 보다 세밀하게 설정해야 한다.
5. 클러스터 데이터소스 설정
본 절에서는 클러스터 데이터소스의 설정에 대하여 알아본다. 콘솔 툴을 사용한 설정 방법은 JEUS Reference 안내서의 add-cluster-data-source를 참고한다.
5.1. 클러스터 데이터소스 설정
[MASTER]domain1.adminServer>add-cluster-data-source -id cds1 -cds ds1,ds2 Successfully performed the ADD operation for cluster data source [cds1] to domain. Check the results using "add-cluster-data-source". [MASTER]domain1.adminServer>addcds Shows the current configuration. Data sources in domain ==================================================================== +------+-----------------------------------------------------------+ | ds1 | common data source | | ds2 | common data source | | cds1 | cluster data source | +------+-----------------------------------------------------------+ ====================================================================
다음은 각 설정 항목에 대한 설명이다.
-
기본 정보
항목 설명 Data Source Id
클러스터 데이터소스의 ID이다. 하나의 도메인에서 클러스터 데이터소스 ID는 클러스터 데이터소스의 유일한 식별자로서 동작하도록 설정해야 한다.
Export Name
클러스터 데이터소스의 JNDI 이름이다.
서로 다른 두 클러스터 데이터소스가 서로 다른 서버에 JNDI bind되는 것을 보장할 수 있으면 해당 클러스터 데이터소스들은 서로 같은 JNDI 이름을 가질 수 있다. 이는 임의의 서버에서 동일한 JNDI 이름을 가지는 서로 다른 데이터소스를 허용하지 않음을 의미한다. 설정되지 않으면 클러스터 데이터소스 ID를 JNDI 이름으로 사용한다.
Data Source Selector
클러스터 데이터소스로부터 커넥션을 얻을 때 사용자나 개발자가 특정 컴포넌트 데이터소스 선택에 대한 정책을 직접 정의할 수 있다.
jeus.jdbc.helper.DataSourceSelector 인터페이스를 구현하고 그 구현 클래스의 패키지 이름을 포함하는 이름을 적어준다. 자세한 내용은 "DataSourceSelector 인터페이스"를 참고한다.
이 항목을 설정하면 Load Balance 설정은 의미가 없다. 정책을 정의할 때는 대체로 동기화를 고려해야 하며 이는 구현자의 몫이다.
Load Balance
Load Balancing 여부를 설정한다. 이 설정값이 true이면 'Use Failback' 설정은 적용되지 않는다.
Component Data Sources
클러스터 데이터소스에 속한 컴포넌트 데이터소스들의 데이터소스 ID를 명시한다. 명시된 순서대로 주 데이터소스의 역할을 맡게 된다.
-
고급 선택사항
항목 설명 Is Pre Conn
클러스터 데이터소스에 속한 컴포넌트 데이터소스들의 Connection Pool을 미리 생성할지 여부를 결정한다. 컴포넌트 데이터소스들의 Connection Pool을 미리 생성해놓으면 성능상으로 이점이 있으나 리소스의 절약면에서는 좋지 못하다.
Use Failback
이전 버전의 JEUS에서는 Failover만을 지원했으므로 이에 대한 호환성을 위해 제공하는 옵션이다.
보조 데이터소스로 Failover한 후에 주 데이터소스로 Failback할 것인지의 여부를 설정한다. 기본적으로 Failback을 시도한다. Failback을 위해서는 반드시 주 데이터소스에 대하여 'Check Query' 및 'Check Query Period' 항목을 설정해야 한다.
DataSource Affinity
트랜잭션 사용 중 데이터소스에 대한 Affinity 설정 여부를 정한다. 이 설정이 켜지면 트랜잭션 처리가 하나의 멤버 데이터소스 인스턴스에 한정하여 이루어져 글로벌 트랜잭션은 처리 성능 향상을 도모할 수 있고, XA Emulation을 설정한 로컬 트랜잭션도 클러스터 데이터소스 사용 간 보장 될 수 있다.
Ons Support
ONS와 결합된 클러스터 데이터소스를 설정한다. ONS와 결합된 클러스터 데이터소스는 컴포넌트 데이터소스의 실패 및 복구 여부를 ONS를 통하여 보다 효과적으로 감지할 수 있다. 특히나 Load Balancing 방식일 때는 Runtime Load Balancing Advisory를 이용하여 좀 더 효율적인 Load Balancing을 제공하게 된다.
다음과 같은 하위 설정이 있다.
-
Ons Config
ONS상의 각 RAC 노드들이 ONS 통신에 사용하는 IP, 포트를 설정한다. 클러스터 데이터소는 설정된 IP, 포트들에 소켓 연결을 맺어 ONS 클라이언트로 동작하게 된다.
다음과 같은 형식으로 적는다.
nodes=host1:6200,host2:6200
-
DataSourceSelector 인터페이스
Data Source Selector 설정에서 언급한 jeus.jdbc.helper.DataSourceSelector 인터페이스의 명세는 다음과 같다. 컴포넌트 데이터소스 선택에 대한 정책을 직접 정의하려면 이 인터페이스를 구현하고 해당 구현 클래스를 Data Source Selector로서 설정하면 된다.
public interface DataSourceSelector { public void setComponentDataSourceList(List<String> componentDataSourceList); public String selectDataSource(); }
메소드 | 설명 |
---|---|
setComponentDataSourceList() |
클러스터 데이터소스에 속한 컴포넌트 데이터소스들의 ID 리스트를 설정한다. |
selectDataSource() |
클러스터 데이터소스에 속한 컴포넌트 데이터소스 선택에 대한 정책 정의를 위해 구현해야 하는 메소드이다. 리턴값은 정의된 정책을 통하여 선택된 데이터소스의 ID가 되어야 한다. 대부분의 환경에서 클러스터 데이터소스로부터 Connection을 얻을 때는 다수의 요청 Thread들이 동시에 접근할 것이므로 정책을 정의할 때는 대체로 동기화에 대한 고려가 필요하며 그것은 구현자의 몫이다. |
위의 명세를 바탕으로 다음과 같은 Customize된 DataSourceSelector 구현이 가능하다. 이 DataSourceSelector 구현체는 클러스터 데이터소스에 참여하는 2개의 데이터소스들에 대하여 2대 1의 선택 비율을 정의하고 있다.
package foo.bar; import jeus.jdbc.helper.DataSourceSelector public class MyDataSourceSelector implements DataSourceSelector { List<String> componentDataSourceList = new ArrayList<String>(); // 동기화 보장 AtomicInteger dataSourceIndex = new AtomicInteger(0); public void setComponentDataSourceList(List<String> componentDataSourceList) { this.componentDataSourceList.addAll(componentDataSourceList); } public String selectDataSource() { int reminder = (dataSourceIndex.getAndIncrement() & 0x7fffffff) % 3; if(reminder < 2) { return componentDataSourceList.get(0); } else { return componentDataSourceList.get(1); } } }
5.2. 클러스터 데이터소스에 속한 컴포넌트 데이터소스 설정
클러스터 데이터소스는 자신에 속한 컴포넌트 데이터소스들에 Connection 요청 처리를 위임하는 방식으로 동작한다. Load Balance 설정이 되어있지 않다면 클러스터 데이터소스는 항상 주 컴포넌트 데이터소스로 Connection 요청 처리를 위임한다. 그러나 만약 주 컴포넌트 데이터소스에 이상이 있는 것으로 판단할 경우에는 새로운 컴포넌트 데이터소스를 주 컴포넌트 데이터소스로 삼아 Connection 요청 처리에 문제가 없도록 수습하는데 이것이 바로 클러스터 데이터소스의 Failover다.
Failover 이후 Failback하기 위해서는 최초의 주 컴포넌트 데이터소스가 복구된 것을 확인해야할 필요가 있다. 이는 해당 컴포넌트 데이터소스에 주기적으로 Check Query를 보내 이루어지므로 클러스터 데이터소스에서 Failback 기능을 이용하기 위해서는 클러스터 데이터소스에 속한 모든 컴포넌트 데이터소스들에 대하여 'Check Query' 및 'Check Query Period' 항목을 설정할 필요가 있다. 만약 Failover만을 사용하기 원한다면 'Use Failback' 항목을 false로 설정하면 된다. 수동으로 Failback 명령을 내릴 수 있는데 이에 대해서는 JEUS Reference 안내서의 control-cluster-data-source를 참고한다.
컴포넌트 데이터소스의 Destroy Policy On Check Query 설정은 ALL_CONNECTIONS로 하는 것이 좋다. 그렇지 않으면 Failover 이후에도 이상이 감지된 컴포넌트 데이터소스의 Connection Pool에 사용이 불가능한 Connection들이 한동안 남아있게 되기 때문이다. 물론 이들은 주기적인 Connection 점검에 의해서 정리가 되지만 Failover가 이뤄지는 시점에 제거되는 것이 바람직하다. |
6. 데이터소스 관련 설정 동적 변경
JEUS 7의 주된 특징 중 하나는 일부 설정에 대한 동적 변경의 지원이다. 설정 동적 변경을 지원한다는 것은 변경한 설정을 JEUS 재기동 없이 런타임에 즉시 반영함을 의미한다. 설정 동적 변경에 대한 보다 자세한 내용은 JEUS Domain 안내서의 도메인 설정변경을 참고한다.
본 절에서는 예시를 통해 데이터소스와 관련된 설정의 동적 변경 방법에 대해 설명한다. 보다 나은 이해를 위해서는 JEUS 도메인 구조 및 도메인에서의 데이터소스 관리 구조 등에 대한 이해와 데이터소스의 각 설정 항목의 쓰임 등에 대한 숙지가 필요하다. JEUS 도메인 구조에 대해서는 JEUS Domain 안내서의 구성요소를 참고한다. 도메인에서의 데이터소스 관리 구조와 데이터소스의 각 설정 항목의 쓰임에 대해서는 각각 데이터소스 및 Connection Pool 관리와 데이터소스 설정을 참고한다.
동적 변경은 콘솔 툴을 통해서 수행될 수 있으므로 본 절에서는 두 가지 방법 모두에 대해서 함께 설명한다. 콘솔 툴을 통한 방법을 설명할 때는 편의상 축약된 명령어 및 옵션의 이름을 사용한다. 축약된 명령어 및 옵션의 이름과 명령어의 세부 사용 방법은 콘솔 툴에서 명령어 이름을 인자로 help를 수행하거나 JEUS Reference 안내서의 데이터소스 관련 명령어 및 Connection Pool 제어 및 모니터링 명령어를 참고하면 확인할 수 있다.
설명을 위해 필요한 몇 가지 사전 작업을 수행한다. 우선 domain1이라는 이름의 도메인과 adminServer라는 이름의 MASTER를 생성한다. MASTER를 기동한 후 각각 server1, server2, server3라는 이름을 갖는 3개의 MS를 domain1에 추가하고 이들 또한 기동한다. 그리고 이들 중 server2와 server3은 cluster1이라는 이름의 클러스터로 묶는다. 도메인 및 클러스터, 서버 관련 설정 방법은 JEUS Domain 안내서의 도메인 생성 및 JEUS 클러스터링, JEUS Server 안내서의 JEUS 설정을 참고한다. 이후로는 앞서 언급한 사전 작업이 모두 완료되었음을 가정한다.
각각의 예제는 서로 연관하여 시나리오를 구성해 설명하므로 본 절의 내용은 기술된 순서대로 읽어가기 바란다. |
6.1. 데이터소스 추가
데이터소스의 동적인 추가가 가능하다. 데이터소스의 추가란 도메인에 데이터소스의 설정을 등록하여 도메인에 속한 서버 및 클러스터에 의해 참조될 수 있는 상태로 만드는 작업이다.
콘솔 툴 사용
콘솔 툴에서 add-data-source 명령어를 수행하면 동적으로 데이터소스를 도메인에 추가할 수 있다. add-data-source를 수행하여 데이터소스를 추가하기 위해서는 데이터소스 각 세부 설정에 해당하는 옵션값들을 설정해야 한다. add-data-source에 대한 보다 자세한 사용법은 JEUS Reference 안내서의 add-data-source를 참고한다.
다음은 add-data-source를 수행하여 필요한 몇몇 설정들을 입력하고 데이터소스 ID가 ds1인 데이터소스를 domain1에 추가하는 예이다.
[MASTER]domain1.adminServer>add-data-source -id ds1 -dst ConnectionPoolDataSource -dscn oracle.jdbc.pool.OracleConnectionPoolDataSource -sn 192.168.1.165 -pn 1521 -dn ora10g -user jeustest1 -password jeustest1 -property driverType;java.lang.String;thin Successfully performed the ADD operation for data source [ds1] to domain. Check the results using "add-data-source"
ds1이 추가된 것은 위의 결과 메시지에서 알 수 있듯이 add-data-source를 수행하여 확인할 수 있다.
[MASTER]domain1.adminServer>add-data-source Shows the current configuration Data sources in domain ==================================================================== +------+-----------------------------------------------------------+ | ds1 | common data source | +------+-----------------------------------------------------------+ ====================================================================
이후의 예시를 위해 위와 같은 방법으로 데이터소스 ID가 각각 ds2, ds3인 데이터소스 2개를 더 추가한다. 이후로는 ds2, ds3의 domain1으로의 추가가 완료되었음 가정한다.
6.2. 서버에 데이터소스 등록
도메인에 데이터소스가 추가되긴 했지만 서버에서 실제로 데이터소스를 참조하여 사용하기 위해서는 데이터소스를 서버에 등록해야 한다. 데이터소스가 서버에 등록되어야 데이터소스 정보가 서버의 JNDI Repository에 bind되고 이후 서버에 deploy된 애플리케이션이 이를 lookup할 수 있다. 이 같은 서버로의 데이터소스 등록 작업은 동적으로 처리 가능하다.
콘솔 툴 사용
콘솔 툴에서 add-data-sources-to-server 명령어를 수행하면 동적으로 데이터소스를 서버에 추가할 수 있다. add-data-sources-to-server에 대한 보다 자세한 사용법은 JEUS Reference 안내서의 add-data-sources-to-server를 참고한다.
다음은 add-data-sources-to-server를 수행하여 ds1, ds2를 server1에 등록하는 예이다.
[MASTER]domain1.adminServer>add-data-sources-to-server -server server1 -ids ds1,ds2 Successfully performed the ADD operation for data sources to the server [server1]. Check the results using "add-data-sources-to-server -server server1"
ds1, ds2가 server1에 등록된 것은 위의 결과 메시지를 통해서 알 수 있듯이 'add-data-sources-to-server -server server1'을 수행하여 확인할 수 있다.
[MASTER]domain1.adminServer>add-data-sources-to-server -server server1 Shows the current configuration. Data sources registered in the server [server1]. ========================================================= +--------------------------------------------+----------+ | data sources | ds1, ds2 | +--------------------------------------------+----------+ =========================================================
jndilist를 수행하면 server1의 JNDI Repository에 ds1과 ds2가 bind된 것을 확인할 수 있다. ds1과 ds2의 JNDI 이름을 별도로 입력하지는 않았으므로 각각의 데이터소스 ID가 JNDI 이름으로도 사용되고 있다.
[MASTER]domain1.adminServer>jndilist -server server1 The JNDI list on the server1 List of the context / ================================================================================ +-------------+------------------------------------------------+---------------+ | Name | Value | Local Binding | +-------------+------------------------------------------------+---------------+ | ds1 | jeus.jdbc.info.JDBCBindInfo | true | | ds2 | jeus.jdbc.info.JDBCBindInfo | true | | JEUSMQ_DLQ | jeus.jms.common.destination.JeusQueue | false | | mgmt | jeus.jndi.JNSContext | false | +-------------+------------------------------------------------+---------------+ ================================================================================
6.3. 서버로부터 데이터소스 제거
서버에 등록된 데이터소스는 동적으로 제거될 수도 있다. 데이터소스가 서버로부터 제거될 때에는 데이터소스 정보가 JNDI unbind되며 Connection Pool이 생성되어 있는 경우 Connection Pool은 destroy된다.
콘솔 툴 사용
콘솔 툴에서 remove-data-sources-from-server를 수행하면 동적으로 데이터소스를 서버로부터 제거할 수 있다. remove-data-sources-from-server에 대한 보다 자세한 사용법은 JEUS Reference 안내서의 remove-data-sources-from-server를 참고한다.
다음은 remove-data-sources-from-server를 수행하여 ds2를 server1으로부터 제거하는 예이다.
[MASTER]domain1.adminServer>remove-data-sources-from-server -server server1 -ids ds2 Successfully performed the REMOVE operation for data sources from the server [server1]. Check the results using "remove-data-sources-from-server -server server1"
remove-data-sources-from-server -server server1을 수행하면 server1으로부터 ds2가 제거되고 ds1만 남아있는 것을 확인할 수 있다.
[MASTER]domain1.adminServer>remove-data-sources-from-server -server server1 Shows the current configuration. Data sources registered in the server [server1]. ============================================================= +---------------------------------------------------+-------+ | data sources | ds1 | +---------------------------------------------------+-------+ =============================================================
jndilist를 수행하면 server1의 JNDI Repository로부터 ds2가 제거되고 ds1만 bind되어 있는 것을 확인할 수 있다.
[MASTER]domain1.adminServer>jndilist -server server1 The JNDI list on the server1 List of the context / ================================================================================ +-------------+------------------------------------------------+---------------+ | Name | Value | Local Binding | +-------------+------------------------------------------------+---------------+ | ds1 | jeus.jdbc.info.JDBCBindInfo | true | | JEUSMQ_DLQ | jeus.jms.common.destination.JeusQueue | false | | mgmt | jeus.jndi.JNSContext | false | +-------------+------------------------------------------------+---------------+ ================================================================================
6.4. 클러스터에 데이터소스 등록
서버에 데이터소스를 등록했던 것처럼 클러스터에도 데이터소스를 등록할 수 있다.
클러스터에 등록된 데이터소스는 클러스터에 속한 모든 서버들에서 유효하다. 즉, 클러스터에 속한 서버는 클러스터에 등록된 데이터소스를 마치 자신이 그 데이터소스를 등록한 것처럼 사용할 수 있다. 데이터소스는 서버에 동적으로 등록될 수 있었던 것처럼 클러스터에도 동적으로 등록될 수 있다.
콘솔 툴 사용
콘솔 툴에서 add-data-sources-to-cluster 명령어를 수행하면 동적으로 데이터소스를 클러스터에 등록할 수 있다. add-data-sources-to-cluster에 대한 보다 자세한 사용법은 JEUS Reference 안내서의 add-data-sources-to-cluster를 참고한다.
다음은 add-data-sources-to-cluster를 수행하여 ds2, ds3를 cluster1에 등록하는 예이다.
[MASTER]domain1.adminServer>add-data-sources-to-cluster -cluster cluster1 -ids ds2,ds3 Successfully performed the ADD operation for data sources to the cluster [cluster1]. Check the results using "add-data-sources-to-cluster -cluster cluster1"
ds2, ds3가 cluster1에 등록된 것은 위의 결과 메시지를 통해서 알 수 있듯이 'add-data-sources-to-cluster -cluster cluster1'을 수행하여 확인할 수 있다.
[MASTER]domain1.adminServer>add-datas-sources-to-cluster -cluster cluster1 Shows the current configuration. The data sources registered in the cluster [cluster1]. ========================================================= +--------------------------------------------+----------+ | data sources | ds2, ds3 | +--------------------------------------------+----------+ =========================================================
이제 cluster1에 데이터소스 ds2와 ds3가 등록되었으므로 cluster1에 속한 server2와 server3는 ds2와 ds3를 자신이 등록한 것처럼 사용할 수 있다. 이는 곧 server2와 server3의 각각의 JNDI Repository에 ds2, ds3가 JNDI bind되었음을 의미한다.
jndilist 명령어를 수행하여 server2의 JNDI Repository를 확인하면 ds2와 ds3가 JNDI bind되어 있음을 확인할 수 있다.
[MASTER]domain1.adminServer>jndilist -server server2 The JNDI list on the server2 List of the context / ================================================================================ +-------------+------------------------------------------------+---------------+ | Name | Value | Local Binding | +-------------+------------------------------------------------+---------------+ | ds2 | jeus.jdbc.info.JDBCBindInfo | true | | ds3 | jeus.jdbc.info.JDBCBindInfo | true | | JEUSMQ_DLQ | jeus.jms.common.destination.JeusQueue | false | | mgmt | jeus.jndi.JNSContext | false | +-------------+------------------------------------------------+---------------+ ================================================================================
또한 jndilist를 수행하여 server3의 JNDI Repository를 확인하면 ds2와 ds3가 JNDI bind되어 있음을 확인할 수 있다.
[MASTER]domain1.adminServer>jndilist -server server3 The JNDI list on the server3 List of the context / ================================================================================ +-------------+------------------------------------------------+---------------+ | Name | Value | Local Binding | +-------------+------------------------------------------------+---------------+ | ds2 | jeus.jdbc.info.JDBCBindInfo | true | | ds3 | jeus.jdbc.info.JDBCBindInfo | true | | JEUSMQ_DLQ | jeus.jms.common.destination.JeusQueue | false | | mgmt | jeus.jndi.JNSContext | false | +-------------+------------------------------------------------+---------------+ ================================================================================
6.5. 클러스터로부터 데이터소스 제거
서버로부터 데이터소스를 동적으로 제거했던 것처럼 클러스터로부터 데이터소스를 동적으로 제거할 수 있다. 클러스터에 등록된 데이터소스가 제거되면 그것에 의존하여 데이터소스를 사용하던 클러스터 내의 모든 서버들은 더 이상 그 데이터소스를 사용할 수 없게 된다. 즉, 그러한 서버들은 클러스터로부터 데이터소스가 제거될 때 데이터소스 정보를 JNDI unbind하며 Connection Pool이 생성되어있는 경우 Connection Pool을 destroy한다.
콘솔 툴 사용
콘솔 툴에서 remove-data-sources-from-cluster 명령어를 수행하면 동적으로 데이터소스를 클러스터로부터 제거할 수 있다. remove-data-sources-from-cluster에 대한 보다 자세한 사용법은 JEUS Reference 안내서의 remove-data-sources-from-cluster를 참고한다.
다음은 remove-data-sources-from-cluster를 수행하여 ds2를 cluster1으로부터 제거하는 예이다.
[MASTER]domain1.adminServer>remove-data-sources-from-cluster -cluster cluster1 -ids ds2 Successfully performed the REMOVE operation for data sources from the cluster [cluster1]. Check the results using "remove-data-sources-from-cluster -cluster cluster1"
remove-data-sources-from-cluster -cluster cluster1을 수행하면 cluster1으로부터 ds2가 제거되고 ds3만 남아있는 것을 확인할 수 있다.
[MASTER]domain1.adminServer>remove-data-sources-from-cluster -cluster cluster1 Shows the current configuration. The data sources registered in the cluster [cluster1]. ============================================================= +---------------------------------------------------+-------+ | data sources | ds3 | +---------------------------------------------------+-------+ =============================================================
이제 cluster1으로부터 데이터소스 ds2가 제거되었으므로 cluster1에 속한 server2와 server3는 더 이상 ds2를 자신이 등록한 것처럼 사용할 수 없다. 이는 곧 server2와 server3의 각각의 JNDI Repository에서 ds2가 JNDI unbind되었으며 ds2의 Connection Pool이 생성되어 있었던 경우 이것 또한 destroy되었음을 의미한다.
jndilist를 수행하여 server2의 JNDI Repository를 확인하면 server2가 더 이상 ds2를 JNDI bind하고 있지 않음을 확인할 수 있다.
[MASTER]domain1.adminServer>jndilist -server server2 The JNDI list on the server2 List of the context / ================================================================================ +-------------+------------------------------------------------+---------------+ | Name | Value | Local Binding | +-------------+------------------------------------------------+---------------+ | ds3 | jeus.jdbc.info.JDBCBindInfo | true | | JEUSMQ_DLQ | jeus.jms.common.destination.JeusQueue | false | | mgmt | jeus.jndi.JNSContext | false | +-------------+------------------------------------------------+---------------+ ================================================================================
또한 jndilist를 수행하여 server3의 JNDI Repository를 확인하면 server3 역시 더 이상 ds2를 JNDI bind하고 있지 않음을 확인할 수 있다.
[MASTER]domain1.adminServer>jndilist -server server3 The JNDI list on the server3 List of the context / ================================================================================ +-------------+------------------------------------------------+---------------+ | Name | Value | Local Binding | +-------------+------------------------------------------------+---------------+ | ds3 | jeus.jdbc.info.JDBCBindInfo | true | | JEUSMQ_DLQ | jeus.jms.common.destination.JeusQueue | false | | mgmt | jeus.jndi.JNSContext | false | +-------------+------------------------------------------------+---------------+ ================================================================================
6.6. 클러스터에 서버 추가
클러스터에 동적으로 서버를 추가할 수 있다. 이는 클러스터 및 서버의 설정 변경이지만 클러스터에 서버를 추가함으로 인해 데이터소스 설정도 변경될 수 있으므로 클러스터에 서버가 동적으로 추가되는 경우 데이터소스 설정이 어떻게 영향을 받을 수 있는지 있는지 설명한다.
클러스터에 동적으로 서버가 추가되면 클러스터에 등록된 데이터소스는 클러스터에 추가된 서버에서 유효해진다. 즉, 클러스터에 추가된 서버는 클러스터에 등록된 데이터소스를 마치 자신이 해당 데이터소스를 등록한 것처럼 사용할 수 있다.
반면 서버 자신이 등록한 데이터소스는 더 이상 그 서버에서 유효하지 않게 되므로 서버 자신이 등록한 데이터소스는 JNDI unbind되며 관련 Connection Pool이 생성되어 있는 경우 Connection Pool은 destroy된다.
콘솔 툴 사용
콘솔 툴에서 add-servers-to-cluster 명령어를 수행하면 동적으로 서버를 클러스터에 추가할 수 있다. add-servers-to-cluster에 대한 보다 자세한 사용법은 JEUS Reference 안내서의 add-servers-to-cluster를 참고한다.
다음은 add-servers-to-cluster를 수행하여 server1을 cluster1에 추가하는 예이다.
[MASTER]domain1.adminServer>add-servers-to-cluster cluster1 -servers server1 Successfully performed the ADD operation for The server list for cluster(cluster1).. Check the results using "list-clusters cluster1 or add-servers-to-cluster cluster1"
server1이 cluster1에 추가된 것은 위의 결과 메시지를 통해서 알 수 있듯이 'list-clusters cluster1' 또는 'add-servers-to-cluster cluster1'을 수행하여 확인할 수 있다.
[MASTER]domain1.adminServer>add-servers-to-cluster cluster1 Shows the current configuration. The server list for cluster(cluster1). =================================================================== +-----------------+-----------------------------------------------+ | List of Servers | server2, server3, server1 | +-----------------+-----------------------------------------------+ ===================================================================
이제 server1이 cluster1에 추가되었으므로 server1은 cluster1에 등록된 ds3를 자신이 등록한 것처럼 사용할 수 있다. 이는 곧 server3의 JNDI Repository에 ds3이 JNDI bind 되었음을 의미한다. 또한 server1 자체적으로 등록하고 있던 ds1 역시 여전히 server1에서 유효하다.
jndilist를 수행하여 server1의 JNDI Repository를 확인하면 ds1과 더불어 ds3가 JNDI bind된 것을 확인할 수 있다.
[MASTER]domain1.adminServer>jndilist -server server1 The JNDI list on the server1 List of the context / ================================================================================ +-------------+------------------------------------------------+---------------+ | Name | Value | Local Binding | +-------------+------------------------------------------------+---------------+ | ds1 | jeus.jdbc.info.JDBCBindInfo | true | | ds3 | jeus.jdbc.info.JDBCBindInfo | true | | JEUSMQ_DLQ | jeus.jms.common.destination.JeusQueue | false | | mgmt | jeus.jndi.JNSContext | false | +-------------+------------------------------------------------+---------------+ ================================================================================
6.7. 클러스터로부터 서버 삭제
클러스터로부터 동적으로 서버를 삭제할 수 있다. 클러스터에 동적으로 서버를 추가하는 것처럼 클러스터로부터 동적으로 서버를 삭제하는 것 또한 클러스터 및 서버의 설정 변경이지만 클러스터로부터 서버를 삭제함으로 인해 데이터소스 설정도 변경될 수 있으므로 클러스터로부터 서버가 동적으로 삭제되는 경우 데이터소스 설정이 어떻게 영향을 받을 수 있는지 설명한다.
클러스터로부터 동적으로 서버가 삭제되면 클러스터에 등록된 데이터소스는 클러스터로부터 삭제된 서버에서 더 이상 유효하지 않다. 즉, 클러스터로부터 삭제된 서버는 클러스터에 등록된 모든 데이터소스 정보를 JNDI unbind하며 Connection Pool이 생성되어있는 경우 Connection Pool을 Destroy한다.
반면 서버 자신이 등록한 데이터소스는 다시 그 서버에서 유효해지므로 서버 자신이 등록한 데이터소스는 JNDI bind되며 Connection Pool을 생성하여 사용할 수 있게 된다.
콘솔 툴 사용
콘솔 툴에서 remove-servers-from-cluster 명령어를 수행하면 동적으로 서버를 클러스터로부터 삭제할 수 있다. remove-servers-from-cluster에 대한 보다 자세한 사용법은 JEUS Reference 안내서의 remove-servers-from-cluster를 참고한다.
다음은 remove-servers-from-cluster를 수행하여 server3을 cluster1으로부터 삭제하는 예이다.
[MASTER]domain1.adminServer>remove-servers-from-cluster cluster1 -servers server3 Successfully performed the REMOVE operation for The server list for cluster(cluster1).. Check the results using "list-clusters cluster1 or remove-servers-from-cluster cluster1"
server3이 cluster1로부터 삭제된 것은 위의 결과 메시지를 통해서 알 수 있듯이 'list-clusters cluster1' 또는 'remove-servers-from-cluster cluster1'을 수행하여 확인할 수 있다.
[MASTER]domain1.adminServer>remove-servers-from-cluster cluster1 Shows the current configuration. The server list for cluster(cluster1). =========================================================== +-----------------+---------------------------------------+ | List of Servers | server2, server1 | +-----------------+---------------------------------------+ ===========================================================
이제 server3가 cluster1으로부터 삭제되었으므로 server3은 더 이상 cluster1에 등록된 ds3를 자신이 등록한 것처럼 사용할 수 없다. 이는 곧 server3의 JNDI Repository에서 ds3가 JNDI unbind되었으며 ds3의 Connection Pool이 생성되어 있었던 경우 이것 또한 destroy되었음을 의미한다.
jndilist를 수행하여 server3의 JNDI Repository를 확인하면 ds3가 사라진 것을 확인할 수 있다.
[MASTER]domain1.adminServer>jndilist -server server3 The JNDI list on the server3 List of the context / ================================================================================ +-------------+------------------------------------------------+---------------+ | Name | Value | Local Binding | +-------------+------------------------------------------------+---------------+ | JEUSMQ_DLQ | jeus.jms.common.destination.JeusQueue | false | | mgmt | jeus.jndi.JNSContext | false | +-------------+------------------------------------------------+---------------+ ================================================================================
6.8. 클러스터 삭제
도메인으로부터 클러스터를 동적으로 삭제할 수 있다. 이는 도메인 및 클러스터의 설정 변경이지만 도메인으로부터 클러스터를 삭제함으로 인해 데이터소스 설정도 변경될 수 있으므로 도메인으로부터 클러스터가 동적으로 삭제되는 경우 데이터소스 설정이 어떻게 영향을 받을 수 있는지 설명한다.
클러스터가 도메인으로부터 삭제되면 클러스터에 등록되어 있던 모든 데이터소스들은 클러스터에 속해있던 서버들에서 더 이상 유효하지 않다. 즉, 삭제된 클러스터에 속했있던 서버들은 클러스터에 등록되어 있던 모든 데이터소스 정보를 JNDI unbind하며 Connection Pool이 생성되어있는 경우 Connection Pool을 destroy한다. 반면 서버 자신이 등록한 데이터소스는 다시 해당 서버에서 유효해지므로 서버 자신이 등록한 데이터소스는 JNDI bind되며 Connection Pool을 생성하여 사용할 수 있게 된다.
콘솔 툴 사용
콘솔 툴에서 remove-cluster를 수행하면 동적으로 클러스터를 도메인으로부터 삭제할 수 있다. remove-cluster에 대한 보다 자세한 사용법은 JEUS Reference 터를 도메인으로부터 삭제할 수 있다. remove-cluster에 대한 보다 자세한 사용법은 JEUS Reference 안내서의 remove-cluster를 참고한다.
다음은 remove-cluster를 수행하여 cluster1을 domain1으로부터 삭제하는 예이다.
[MASTER]domain1.adminServer>remove-cluster cluster1 Successfully performed the REMOVE operation for cluster (cluster1). Check the results using "list-clusters or remove-cluster"
cluster1이 domain1으로부터 삭제된 것은 위의 결과 메시지를 통해서 알 수 있듯이 list-clusters 또는 remove-cluster를 수행하여 확인할 수 있다.
[MASTER]domain1.adminServer>remove-cluster Shows the current configuration. cluster list ================================================================= +-------------------------------------------------------+-------+ | List of Clusters | empty | +-------------------------------------------------------+-------+ =================================================================
이제 cluster1이 domain1으로부터 삭제되었으므로 cluster1에 속해있던 server1과 server2는 더 이상 cluster1에 등록되어 있던 ds3를 자신이 등록한 것처럼 사용할 수 없다. 이는 곧 server1과 server2 각각의 JNDI Repository에서 ds3가 JNDI unbind되었으며 ds3의 Connection Pool이 생성되어 있었던 경우 이것 또한 destroy되었음을 의미한다.
jndilist를 수행하여 server1의 JNDI Repository를 확인하면 ds3는 JNDI unbind되고 자신이 등록한 ds1만 JNDI bind되어 있는 것을 확인할 수 있다.
[MASTER]domain1.adminServer>jndilist -server server1 The JNDI list on the server1 List of the context / ================================================================================ +-------------+------------------------------------------------+---------------+ | Name | Value | Local Binding | +-------------+------------------------------------------------+---------------+ | ds1 | jeus.jdbc.info.JDBCBindInfo | true | | JEUSMQ_DLQ | jeus.jms.common.destination.JeusQueue | false | | mgmt | jeus.jndi.JNSContext | false | +-------------+------------------------------------------------+---------------+ ================================================================================
또한 jndilist를 수행하여 server2의 JNDI Repository를 확인하면 어떤 데이터소스도 JNDI bind되어 있지 않음을 확인할 수 있다.
[MASTER]domain1.adminServer>jndilist -server server2 The JNDI list on the server2 List of the context / ================================================================================ +-------------+------------------------------------------------+---------------+ | Name | Value | Local Binding | +-------------+------------------------------------------------+---------------+ | JEUSMQ_DLQ | jeus.jms.common.destination.JeusQueue | false | | mgmt | jeus.jndi.JNSContext | false | +-------------+------------------------------------------------+---------------+ ================================================================================
6.9. 데이터소스 삭제
도메인으로부터 동적으로 데이터소스를 삭제할 수 있다. 데이터소스가 도메인으로부터 삭제되면 삭제된 데이터소스는 그것을 사용하던 서버와 클러스터에서 더 이상 유효하지 않다. 즉 삭제된 데이터소스를 사용하던 서버들은 그 데이터소스 정보를 JNDI unbind하며 Connection Pool이 생성되어있는 경우 Connection Pool을 destroy한다.
콘솔 툴 사용
콘솔 툴에서 remove-data-source를 수행하면 동적으로 데이터소스를 도메인으로부터 삭제할 수 있다. remove-data-source에 대한 보다 자세한 사용법은 JEUS Reference 안내서의 remove-data-source를 참고한다.
다음은 remove-data-source를 수행하여 ds1을 domain1으로부터 삭제하는 예이다.
[MASTER]domain1.adminServer>remove-data-source -id ds1 Successfully performed the REMOVE operation for data source [ds1] from the domain. ================================================================================ +---------------------------------------------------------+--------+-----------+ | resources.dataSource.database | MODIFY | ACTIVATED | | servers.server.{? name == 'server1' }.dataSources | MODIFY | ACTIVATED | +---------------------------------------------------------+--------+-----------+ ================================================================================ Check the results using "remove-data-source"
위의 결과를 보면 remove-data-source를 수행하여 ds1를 삭제할 때 ds1를 등록하고 있던 server1에도 어떠한 변화가 생겼음을 짐작할 수 있다. 위의 결과는 ds1이 domain1에서 삭제되는 동시에 server1에 등록되었던 ds1 정보도 제거됨을 표시하고 있다. 이와 같이 동적으로 설정을 변경하는 명령어를 수행하면 그와 연관되어 발생하는 모든 설정 변경의 런타임 반영 여부를 확인할 수 있다. 동적 설정 변경 명령어의 보다 자세한 사용법은 JEUS Domain 안내서의 도메인 설정변경을 참고한다.
ds1이 삭제된 것은 위의 결과 메시지를 통해서 알 수 있듯이 remove-data-source를 아무 옵션 없이 수행하여 확인할 수 있다.
[MASTER]domain1.adminServer>remove-data-source Shows the current configuration. Data sources in domain ==================================================================== +------+-----------------------------------------------------------+ | ds2 | common data source | | ds3 | common data source | +------+-----------------------------------------------------------+ ====================================================================
이제 ds1이 domain1으로부터 삭제되었으므로 server1은 더 이상 ds1을 사용할 수 없다. 이는 곧 server1의 JNDI Repository에서 ds1이 JNDI unbind되었으며 ds1의 Connection Pool이 생성되어 있었던 경우 이것 또한 destroy되었음을 의미한다.
jndilist를 수행하여 server1의 JNDI Repository를 확인하면 ds1이 사라진 것을 확인할 수 있다.
[MASTER]domain1.adminServer>jndilist -server server1 The JNDI list on the server1 List of the context / ================================================================================ +-------------+------------------------------------------------+---------------+ | Name | Value | Local Binding | +-------------+------------------------------------------------+---------------+ | JEUSMQ_DLQ | jeus.jms.common.destination.JeusQueue | false | | mgmt | jeus.jndi.JNSContext | false | +-------------+------------------------------------------------+---------------+ ================================================================================
6.10. 데이터소스 설정 변경
지금까지는 데이터소스, 서버, 클러스터를 추가/삭제할 때 데이터소스의 관리가 어떻게 이루어지는지 살펴보았다. 본 절에서는 데이터소스 자체의 설정 변경에 대해서 설명한다.
데이터소스 설정에서 살펴봤던 것처럼 데이터소스의 설정은 크게 드라이버 Setup 등에 필요한 기본 설정과 Connection Pool 설정으로 이루어져있다. 이 중 드라이버 Setup 설정은 동적 변경이 불가능하지만 그 외의 기본 설정 몇 가지와 Connection Pool 설정의 대부분은 동적 변경이 가능하다. 동적 변경이 불가능한 설정은 변경을 시도하는 경우 변경 사항이 설정 파일에는 기록되나 런타임에 반영되지는 않는다. 이는 곧 서버를 다시 기동해야 변경 사항을 런타임에 반영할 수 있음을 의미한다. 반면 동적 변경이 가능한 설정은 변경을 시도할 때 변경 사항이 설정 파일에도 기록되며 런타임에도 즉시 반영된다.
동적 변경이 가능한 데이터소스 설정에는 여러 가지가 있는데 그 중 비교적 동적 변경 빈도가 높을 것으로 예상되는 Connection Pool의 Connection 최솟값, 최댓값 설정을 예로 설명한다. 변경 대상이 되는 데이터소스는 ds2로 하며 실제로 Connection Pool의 Connection 최솟값, 최댓값 설정 변경이 동적으로 런타임에 반영되었는지 확인하기 위해 ds2를 server1에 등록하고 Connection Pool을 생성한다. 데이터소스를 서버에 등록하는 방법은 앞서 알아보았으므로 여기에서는 실제 ds2 Connection Pool을 server1에 생성하는 방법부터 설명한다.
콘솔 툴 사용
Connection Pool은 콘솔 툴에서 create-connection-pool을 수행하여 생성할 수 있다. create-connection-pool에 대한 보다 자세한 사용법은 JEUS Reference 안내서의 create-connection-pool을 참고한다.
다음은 create-connection-pool을 수행하여 ds2의 Connection Pool을 생성하는 예이다. ds2의 Connection Pool이 server1에 생성되었음을 결과 메시지로부터 알 수 있다.
[MASTER]domain1.adminServer>create-connection-pool -id ds2 Servers that successfully created a connection pool : server1 Servers that failed to create a connection pool : none.
connection-pool-info를 수행하면 Connection Pool의 런타임 Connection 최솟값, 최댓값을 확인할 수 있다. 이 명령어에 대한 보다 자세한 설명은 JEUS Reference 안내서의 connection-pool-info를 참고한다.
다음은 connection-pool-info를 수행하여 server1에 생성된 ds2 Connection Pool의 런타임 Connection 최솟값, 최댓값을 확인하는 예이다.
[MASTER]domain1.adminServer>connection-pool-info -server server1 The connection pool information on the server [server1]. ================================================================================ +--------+-----+-----+--------+-----+--------+-----+--------+-----+-----+------+ | Connec | Min | Max | Active | Act | Active | Idle| Dispos | Tot | Wait| Enab | | tion | | | Max | ive | Average| | able | al | | led | |Pool ID | | | | | | | | | | | +--------+-----+-----+--------+-----+--------+-----+--------+-----+-----+------+ | ds2 | 2 | 30 | 0 | 0 | 0.0 | 2 | 0 | 2 | fal | true | | | | | | | | | | |se | | +--------+-----+-----+--------+-----+--------+-----+--------+-----+-----+------+ * : has not been created, total = active + idle + disposable ================================================================================
ds2 Connection Pool의 런타임 Connection 최솟값이 2, 최댓값이 30으로 설정되어 있는 것을 확인할 수 있다. 이는 ds2을 처음 도메인에 추가할 때 별도로 Connection 최솟값, 최댓값을 설정하지 않아 디폴트로 적용된 값이다.
다음은 각각 2, 30으로 설정되어 있는 ds2의 Connection 최솟값과 최댓값을 변경하는 설명이다.
modify-data-source를 수행하면 동적으로 데이터소스 설정을 변경할 수 있다. help를 수행하거나 JEUS Reference 안내서의 modify-data-source를 참고하면 modify-data-source를 통하여 변경할 수 있는 모든 설정들을 옵션들의 이름으로 유추하여 확인할 수 있다. 동적 변경이 가능한 설정과 관련된 옵션에는 태그를 붙여 두었으므로 이를 통해 어떤 설정이 동적으로 변경 가능한지도 알 수 있다.
다음은 modify-data-source를 수행하여 ds2의 Connection 최솟값과 최댓값을 각각 10, 50으로 변경하는 예이다.
[MASTER]domain1.adminServer>modify-data-source -id ds2 -min 10 -max 50 Successfully performed the MODIFY operation for configuration of the data source [ds2]. Check the results using "modify-data-source -id ds2"
modify-data-source를 수행하여 변경된 ds2의 설정은 위의 결과 메시지를 통해서 알 수 있듯이 'modify-data-source -id ds2’를 수행하여 확인할 수 있다. min, max가 각각 10, 50으로 설정되어있는 것을 확인할 수 있다.
[MASTER]domain1.adminServer>modify-data-source -id ds2 Shows the current configuration. configuration of the data source [ds2] ================================================================================ +----------------------------+-------------------------------------------------+ | id | ds2 | | export-name | ds2 | | data-source-class-name | oracle.jdbc.pool.OracleConnectionPoolDataSource | | data-source-type | ConnectionPoolDataSource | | server-name | 192.168.1.165 | | port-number | 1521 | | database-name | ora10g | | user | jeustest1 | | password | jeustest1 | | login-timeout | 0 | | auto-commit | DRIVER | | stmt-query-timeout | 0 | | pool-destroy-timeout | 10000 | | property | driverType;java.lang.String;thin | | support-xa-emulation | false | | min | 10 | | max | 50 | | step | 1 | | period | 3600000 | | enable-wait | false | | wait-time | 10000 | | max-use-count | 0 | | dbaTimeout | -1 | | stmt-caching-size | -1 | | stmt-fetch-size | -1 | | connection-trace | false | | get-connection-trace | true | | auto-commit-trace | false | | use-sql-trace | false | | keep-connection-handle-open| false | +----------------------------+-------------------------------------------------+ ================================================================================
다음은 다시 connection-pool-info를 수행하여 server1에 생성된 ds2 Connection Pool의 런타임 Connection 최솟값, 최댓값을 확인하는 예이다. ds2의 런타임 Connection 최솟값, 최댓값이 각각 10, 50으로 변경된 것을 확인할 수 있다.
[MASTER]domain1.adminServer>connection-pool-info -server server1 The connection pool information on the server [server1]. ================================================================================ +--------+-----+-----+--------+-----+--------+-----+--------+-----+-----+------+ | Connec | Min | Max | Active | Act | Active | Idle| Dispos | Tot | Wait| Enab | | tion | | | Max | ive | Average| | able | al | | led | |Pool ID | | | | | | | | | | | +--------+-----+-----+--------+-----+--------+-----+--------+-----+-----+------+ | ds2 | 10 | 50 | 0 | 0 | 0.0 | 10 | 0 | 10 | fal | true | | | | | | | | | | |se | | +--------+-----+-----+--------+-----+--------+-----+--------+-----+-----+------+ * : has not been created, total = active + idle + disposable ================================================================================
6.11. 데이터소스 설정 확인
JEUS 7부터는 설정 파일을 열어 사용자가 직접 수정한 설정에 대해서 책임지지 않는다. 설정 파일을 열어서 설정을 확인하는 것은 그러한 변경과는 관련이 없으나 되도록이면 설정 파일에 직접 접근하는 것을 권장하지 않는다. 이를 위해 데이터소스의 설정을 명령어를 통해 확인할 수 있도록 지원한다.
본 절에서는 콘솔 툴을 사용해서 데이터소스의 설정을 확인하는 방법에 대해서 설명한다.
콘솔 툴 사용
콘솔 툴에서 list-data-sources 명령어를 수행하면 도메인에 존재하는 모든 데이터소스의 목록을 확인할 수 있다.
다음은 list-data-sources의 수행하여 도메인에 존재하는 모든 데이터소스 목록을 확인하는 예이다.
[MASTER]domain1.adminServer>list-data-sources The list of data sources ================================================================================ +----------------+----------------------+--------------------------------------+ | Data Source ID | JNDI Export Name | Data Source Type | +----------------+----------------------+--------------------------------------+ | ds2 | ds2 | ConnectionPoolDataSource | | ds3 | ds3 | ConnectionPoolDataSource | +----------------+----------------------+--------------------------------------+ ================================================================================
특정 데이터소스의 ID를 옵션값으로 입력하면 해당 데이터소스의 전체 설정을 상세히 조회한다.
다음은 list-data-sources를 수행하여 ds2의 상세 설정을 확인하는 예이다.
[MASTER]domain1.adminServer>list-data-sources -id ds2 The configuration of the data source [ds2] ================================================================================ +----------------------------+-------------------------------------------------+ | Configuration name | Configuration value | +----------------------------+-------------------------------------------------+ | id | ds2 | | export-name | ds2 | | data-source-class-name | oracle.jdbc.pool.OracleConnectionPoolDataSource | | data-source-type | ConnectionPoolDataSource | | server-name | 192.168.1.165 | | port-number | 1521 | | database-name | ora10g | | user | jeustest1 | | password | jeustest1 | | login-timeout | 0 | | auto-commit | DRIVER | | stmt-query-timeout | 0 | | pool-destroy-timeout | 10000 | | property | [driverType;java.lang.String;thin] | | support-xa-emulation | false | | min | 10 | | max | 50 | | step | 1 | | period | 3600000 | | enable-wait | false | | wait-time | 10000 | | max-use-count | 0 | | dbaTimeout | -1 | | stmt-caching-size | -1 | | stmt-fetch-size | -1 | | connection-trace | false | | get-connection-trace | true | | auto-commit-trace | false | | use-sql-trace | false | | keep-connection-handle-open| false | +----------------------------+-------------------------------------------------+ ================================================================================
7. 클러스터 데이터소스 설정 동적 변경
본 절에서는 예시를 통해 클러스터 데이터소스와 관련된 설정의 동적 변경 방법에 대해 설명한다. 보다 나은 이해를 위해서는 JEUS 도메인 구조 및 도메인에서의 데이터소스 관리 구조 등에 대한 이해와 클러스터 데이터소스의 각 설정 항목의 사용 등에 대한 숙지가 필요하다.
JEUS 도메인 구조에 대해서는 JEUS Domain 안내서의 구성요소를 참고한다. 도메인에서의 데이터소스 관리 구조와 클러스터 데이터소스의 각 설정 항목의 쓰임에 대해서는 각각 데이터소스 및 Connection Pool 관리와 클러스터 데이터소스 설정을 참고한다.
동적 변경은 콘솔 툴을 통해서 수행될 수 있으므로 본 절에서는 두 가지 방법을 설명한다. 콘솔 툴을 통한 방법을 설명할 때는 편의상 축약된 명령어 및 옵션의 이름을 사용한다. 축약된 명령어 및 옵션의 이름과 명령어의 세부 사용 방법은 콘솔 툴에서 명령어 이름을 인자로 help를 수행하거나 JEUS Reference 안내서의 Connection Pool 제어 및 모니터링 명령어를 참고하면 확인할 수 있다.
설명을 위해 필요한 몇 가지 사전 작업을 수행한다.
우선 domain1이라는 이름의 도메인과 adminServer라는 이름의 Master를 생성한다. Master를 기동한 후 각각 server1, server2, server3라는 이름을 갖는 3개의 MS를 domain1에 추가하고 기동한다. 그리고 server2와 server3는 cluster1이라는 이름의 클러스터로 묶는다. 도메인 및 클러스터, 서버 관련 설정 방법은 JEUS Domain 안내서의 도메인 생성 및 JEUS 클러스터링, JEUS Server 안내서의 JEUS 설정을 참고한다. 이후로는 앞서 언급한 사전 작업이 모두 완료되었음을 가정한다.
각각의 예시를 서로 연관하여 시나리오를 구성해 설명하므로 본 절의 내용은 기술된 순서대로 읽어가기 바란다. |
7.1. 클러스터 데이터소스 추가
일반 데이터소스처럼 클러스터 데이터소스도 동적인 추가가 가능하다. 클러스터 데이터소스를 추가할 때 항상 고려해야 할 것은 클러스터 데이터소스에 묶이는 컴포넌트 데이터소스들도 함께 추가해야 한다는 사실이다.
본 절에서는 데이터소스 ID가 각각 ds1, ds2인 데이터소스들을 컴포넌트 데이터소스로 갖는 클러스터 데이터소스를 domain1에 추가하는 예를 설명한다. 클러스터 데이터소스의 데이터소스 ID는 cds1이다.
콘솔 툴 사용
cds1의 컴포넌트 데이터소스로 동작할 ds1과 ds2를 domain1에 추가해야 한다.
다음은 add-data-source를 수행하여 ds1과 ds2를 domain1에 추가하는 예이다. add-data-source에 대한 보다 자세한 사용법은 JEUS Reference 안내서의 add-data-source를 참고한다.
[MASTER]domain1.adminServer>add-data-source -id ds1 -dst ConnectionPoolDataSource -dscn oracle.jdbc.pool.OracleConnectionPoolDataSource -sn 192.168.1.165 -pn 1521 -dn ora10g -user jeustest1 -password jeustest1 -property driverType;java.lang.String;thin Successfully performed the ADD operation for data source [ds1] to domain. Check the results using "add-data-source" [MASTER]domain1.adminServer>add-data-source -id ds2 -dst ConnectionPoolDataSource -dscn oracle.jdbc.pool.OracleConnectionPoolDataSource -sn 192.168.1.165 -pn 1521 -dn ora10g -user jeustest1 -password jeustest1 -property driverType;java.lang.String;thin Successfully performed the ADD operation for data source [ds2] to domain. Check the results using "add-data-source"
ds1과 ds2를 domain1에 추가했으므로 이제 cds1을 domain1에 추가한다. add-cluster-data-source를 수행하면 동적으로 클러스터 데이터소스를 도메인에 추가할 수 있다. add-cluster-data-source에 대한 보다 자세한 사용법은 JEUS Reference 안내서의 add-cluster-data-source를 참고한다. add-cluster-data-source를 수행하여 데이터소스를 추가하기 위해서는 클러스터 데이터소스 각 세부 설정에 해당하는 옵션값들을 명시해야 한다.
다음은 add-cluster-data-source를 수행하여 필요한 몇몇 설정들을 입력하고 클러스터 데이터소스 ID가 cds1인 데이터소스를 domain1에 추가하는 예이다.
[MASTER]domain1.adminServer>add-cluster-data-source -id cds1 -cds ds1,ds2 Successfully performed the ADD operation for cluster data source [cds1] to domain. Check the results using "add-cluster-data-source"
cds1이 추가된 것은 위의 결과 메시지를 통해서 알 수 있듯이 add-cluster-data-source를 아무 옵션 없이 수행하여 확인할 수 있다.
[MASTER]domain1.adminServer>add-cluster-data-source Shows the current configuration. Data sources in domain ==================================================================== +------+-----------------------------------------------------------+ | ds1 | common data source | | ds2 | common data source | | cds1 | cluster data source | +------+-----------------------------------------------------------+ ====================================================================
7.2. 서버에 클러스터 데이터소스 등록
클러스터 데이터소스도 일반 데이터소스처럼 서버에 등록되어야 사용될 수 있다. 클러스터 데이터소스가 서버에 등록되어야 비로소 클러스터 데이터소스 정보가 서버의 JNDI Repository에 bind되고 이후 서버에 deploy된 애플리케이션이 이를 lookup할 수 있다. 이때 클러스터 데이터소스에 묶인 컴포넌트 데이터소스들 역시 서버에 등록해야 한다는 것을 주의한다.
실제 Connection Pool 서비스를 제공하는 것은 각각의 컴포넌트 데이터소스이며 이들의 Connection Pool은 결국 서버에 생성되므로 클러스터 데이터소스를 등록하는 서버 그 클러스터 데이터소스에 묶인 컴포넌트 데이터소스들을 함께 등록해야 원하는대로 클러스터 데이터소스를 사용할 수 있다.
본 절에서는 cds1을 server1에 등록하는 방법에 대해 설명한다.
콘솔 툴 사용
cds1의 컴포넌트 데이터소스인 ds1과 ds2도 server1에 함께 등록해야 한다.
다음은 add-data-sources-to-server를 수행하여 ds1, ds2, cds1을 server1에 등록하는 예이다. add-data-sources-to-server에 대한 보다 자세한 사용법은 JEUS Reference 안내서의 add-data-sources-to-server를 참고한다.
[MASTER]domain1.adminServer>add-data-sources-to-server -server server1 -ids ds1,ds2,cds1 Successfully performed the ADD operation for data sources to the server [server1]. Check the results using "add-data-sources-to-server -server server1"
ds1, ds2, cds1이 server1에 등록된 것은 위의 결과 메시지를 통해서 알 수 있듯이 'add-data-sources-to-server -server server1'을 수행하여 확인할 수 있다.
[MASTER]domain1.adminServer>add-data-sources-to-server -server server1 Shows the current configuration. Data sources registered in the server [server1]. ========================================================== +--------------+-----------------------------------------+ | data sources | ds1, ds2, cds1 | +--------------+-----------------------------------------+ ==========================================================
jndilist를 수행하면 server1의 JNDI Repository에 ds1, ds2, cds1이 bind된 것을 확인할 수 있다.
[MASTER]domain1.adminServer>jndilist -server server1 The JNDI list on the server1 List of the context / ================================================================================ +-------------+------------------------------------------------+---------------+ | Name | Value | Local Binding | +-------------+------------------------------------------------+---------------+ | cds1 | jeus.jdbc.info.JDBCBindInfo | true | | ds1 | jeus.jdbc.info.JDBCBindInfo | true | | ds2 | jeus.jdbc.info.JDBCBindInfo | true | | JEUSMQ_DLQ | jeus.jms.common.destination.JeusQueue | false | | mgmt | jeus.jndi.JNSContext | false | +-------------+------------------------------------------------+---------------+ ================================================================================
7.3. 서버로부터 클러스터 데이터소스 제거
서버에 등록된 클러스터 데이터소스도 일반 데이터소스처럼 서버로부터 동적으로 제거될 수 있다.
일반 데이터소스와 마찬가지로 클러스터 데이터소스가 서버로부터 제거될 때에는 클러스터 데이터소스 정보가 JNDI unbind된다. 클러스터 데이터소스는 자신의 Connection Pool을 가지지 않고 실제 Connection Pool은 클러스터 데이터소스에 속한 컴포넌트 데이터소스들로부터 생성되므로 클러스터 데이터소스가 서버로부터 제거될 때에는 일반 데이터소스들과는 다르게 Connection Pool의 destroy는 일어나지 않는다. 클러스터 데이터소스에 속했던 컴포넌트 데이터소스들의 Connection Pool이 destroy될 것으로 생각할 수 있으나 컴포넌트 데이터소스 각각은 또한 독립적인 데이터소스로도 기능할 필요가 있을 수도 있으므로 이들에 대한 JNDI unbind나 destroy는 일어나지 않는다.
콘솔 툴 사용
콘솔 툴에서 remove-data-sources-from-server를 수행하면 동적으로 클러스터 데이터소스를 서버로부터 제거할 수 있다. remove-data-sources-from-server에 대한 보다 자세한 사용법은 JEUS Reference 안내서의 remove-data-sources-from-server를 참고한다.
다음은 remove-data-sources-from-server를 수행하여 cds1을 server1으로부터 제거하는 예이다.
[MASTER]domain1.adminServer>remove-data-sources-from-server -server server1 -ids cds1 Successfully performed the REMOVE operation for data sources from the server [server1]. Check the results using "remove-data-sources-from-server -server server1"
cds1이 server1으로부터 제거된 것은 위의 결과 메시지를 통해서 알 수 있듯이 'remove-data-sources-from-server -server server1'을 수행하여 확인할 수 있다.
[MASTER]domain1.adminServer>remove-data-sources-from-server -server server1 Shows the current configuration. Data sources registered in the server [server1]. ========================================================= +--------------------------------------------+----------+ | data sources | ds1, ds2 | +--------------------------------------------+----------+ =========================================================
cds1이 제거되고 ds1과 ds2는 여전히 등록되어 있는 것을 확인할 수 있다.
jndilist를 수행하면 server1의 JNDI Repository로부터 cds1이 unbind된 것을 확인할 수 있다.
[MASTER]domain1.adminServer>jndilist -server server1 The JNDI list on the server1 List of the context / ================================================================================ +-------------+------------------------------------------------+---------------+ | Name | Value | Local Binding | +-------------+------------------------------------------------+---------------+ | ds1 | jeus.jdbc.info.JDBCBindInfo | true | | ds2 | jeus.jdbc.info.JDBCBindInfo | true | | JEUSMQ_DLQ | jeus.jms.common.destination.JeusQueue | false | | mgmt | jeus.jndi.JNSContext | false | +-------------+------------------------------------------------+---------------+ ================================================================================
7.4. 클러스터에 클러스터 데이터소스 등록
클러스터 데이터소스도 일반 데이터소스들처럼 동적으로 클러스터에 등록될 수 있다. 클러스터에 등록된 클러스터 데이터소스는 클러스터에 속한 모든 서버들에서 유효하다. 즉, 클러스터에 속한 서버는 클러스터에 등록된 클러스터 데이터소스를 마치 자신이 그 클러스터 데이터소스를 등록한 것처럼 사용할 수 있다. 클러스터 데이터소스를 서버에 등록할 때처럼 클러스터 데이터소스를 클러스터에 등록할 때에도 클러스터 데이터소스에 묶인 컴포넌트 데이터소스들을 클러스터에 함께 등록해야 한다.
본 절에서는 cds1을 cluster1에 등록하는 과정을 설명한다.
콘솔 툴 사용
cds1의 컴포넌트 데이터소스인 ds1과 ds2도 cluster1에 함께 등록해야 한다.
다음은 콘솔 툴에서 add-data-sources-to-cluster를 수행하여 ds1, ds2, cds1을 cluster1에 등록하는 예이다. add-data-sources-to-cluster에 대한 보다 자세한 사용법은 JEUS Reference 안내서의 add-data-sources-to-cluster를 참고한다.
[MASTER]domain1.adminServer>add-data-sources-to-cluster -cluster cluster1 -ids ds1,ds2,cds1 Successfully performed the ADD operation for data sources to the cluster [cluster1]. Check the results using "add-data-sources-to-cluster -cluster cluster1"
ds1, ds2, cds1이 cluster1에 등록된 것은 위의 결과 메시지를 통해서 알 수 있듯이 'add-data-sources-to-cluster -cluster cluster1'을 수행하여 확인할 수 있다.
[MASTER]domain1.adminServer>add-data-sources-to-cluster -cluster cluster1 Shows the current configuration. The data sources registered in the cluster [cluster1]. ========================================================== +--------------+-----------------------------------------+ | data sources | ds1, ds2, cds1 | +--------------+-----------------------------------------+ ==========================================================
이제 cluster1에 ds1, ds2, cds1이 등록되었으므로 cluster1에 속한 server2와 server3는 ds1, ds2, cds1을 자신이 등록한 것처럼 사용할 수 있다.
jndilist를 수행하여 server2의 JNDI Repository를 확인하면 ds1, ds2, cds1이 JNDI bind된 것을 확인할 수 있다.
[MASTER]domain1.adminServer>jndilist -server server2 The JNDI list on the server2 List of the context / ================================================================================ +-------------+------------------------------------------------+---------------+ | Name | Value | Local Binding | +-------------+------------------------------------------------+---------------+ | cds1 | jeus.jdbc.info.JDBCBindInfo | true | | ds1 | jeus.jdbc.info.JDBCBindInfo | true | | ds2 | jeus.jdbc.info.JDBCBindInfo | true | | JEUSMQ_DLQ | jeus.jms.common.destination.JeusQueue | false | | mgmt | jeus.jndi.JNSContext | false | +-------------+------------------------------------------------+---------------+ ================================================================================
7.5. 클러스터로부터 클러스터 데이터소스 제거
클러스터에 등록된 클러스터 데이터소스도 일반 데이터소스처럼 클러스터로부터 동적으로 제거될 수 있다. 클러스터에 등록된 클러스터 데이터소스가 제거되면 그것에 의존하여 클러스터 데이터소스를 사용하던 클러스터 내의 모든 서버들은 더 이상 그 클러스터 데이터소스를 사용할 수 없게 된다. 즉, 그러한 서버들은 클러스터로부터 클러스터 데이터소스가 제거될 때 클러스터 데이터소스 정보를 JNDI unbind한다. 그러나 클러스터 데이터소스를 서버로부터 제거할 때와 마찬가지로 컴포넌트 데이터소스들의 Connection Pool destroy는 일어나지 않는다.
콘솔 툴 사용
콘솔 툴에서 remove-data-sources-from-cluster를 수행하면 동적으로 클러스터 데이터소스를 클러스터로부터 제거할 수 있다. remove-data-sources-from-cluster의 보다 자세한 사용법은 JEUS Reference 안내서의 remove-data-sources-from-cluster를 참고한다.
다음은 remove-data-sources-from-cluster를 수행하여 cds1을 cluster1으로부터 제거하는 예이다.
[MASTER]domain1.adminServer>remove-data-sources-from-cluster -cluster cluster1 -ids cds1 Successfully performed the REMOVE operation for data sources from the cluster [cluster1]. Check the results using "remove-data-sources-from-cluster -cluster cluster1"
remove-data-sources-from-cluster -cluster cluster1을 수행하면 cluster1으로부터 cds1가 제거되고 ds1, ds2는 남아있는 것을 확인할 수 있다.
[MASTER]domain1.adminServer>remove-data-sources-from-cluster -cluster cluster1 Shows the current configuration. The data sources registered in the cluster [cluster1]. ========================================================= +--------------------------------------------+----------+ | data sources | ds1, ds2 | +--------------------------------------------+----------+ =========================================================
이제 cluster1으로부터 클러스터 데이터소스 cds1이 제거되었으므로 cluster1에 속한 server2와 server3는 더 이상 cds1을 자신이 등록한 것처럼 사용할 수 없다. 이는 곧 server2와 server3의 JNDI Repository에서 cds1이 JNDI unbind 되었음을 의미한다.
jndilist를 수행하면 server2의 JNDI Repository로부터 cds1이 JNDI unbind된 것을 확인할 수 있다.
[MASTER]domain1.adminServer>jndilist -server server2 The JNDI list on the server2 List of the context / ================================================================================ +-------------+------------------------------------------------+---------------+ | Name | Value | Local Binding | +-------------+------------------------------------------------+---------------+ | ds1 | jeus.jdbc.info.JDBCBindInfo | true | | ds2 | jeus.jdbc.info.JDBCBindInfo | true | | JEUSMQ_DLQ | jeus.jms.common.destination.JeusQueue | false | | mgmt | jeus.jndi.JNSContext | false | +-------------+------------------------------------------------+---------------+ ================================================================================
7.6. 클러스터에 서버 추가
클러스터에 동적으로 서버가 추가되면 클러스터에 등록된 클러스터 데이터소스도 클러스터에 등록된 일반 데이터소스들과 마찬가지로 클러스터에 추가된 서버들에서 유효해진다. 즉, 클러스터에 추가된 서버는 클러스터에 등록된 클러스터 데이터소스를 마치 자신이 그 클러스터 데이터소스를 등록한 것처럼 사용할 수 있다.
전체적인 메커니즘은 클러스터에 서버 추가에서의 설명과 유사하므로 별도로 설명하지 않는다. 자세한 내용은 해당 절을 참고한다.
7.7. 클러스터로부터 서버 삭제
클러스터로부터 동적으로 서버가 삭제되면 클러스터에 등록된 클러스터 데이터소스는 클러스터에 등록된 일반 데이터소스들과 마찬가지로 클러스터로부터 삭제된 서버에서 더 이상 유효하지 않다. 즉, 클러스터로부터 삭제된 서버는 클러스터에 등록된 모든 클러스터 데이터소스 정보를 JNDI unbind한다.
전체적인 메커니즘은 클러스터로부터 서버 삭제에서의 설명과 유사하므로 별도로 설명하지 않는다. 자세한 내용은 해당 절을 참고한다.
7.8. 클러스터 삭제
클러스터가 동적으로 도메인에서 삭제되면 클러스터에 등록되어 있던 클러스터 데이터소스들은 클러스터에 등록되어 있던 일반 데이터소스들과 마찬가지로 클러스터에 속해있던 서버들에서 더 이상 유효하지 않다. 즉, 삭제된 클러스터에 속했있던 서버들은 클러스터에 등록되어 있던 모든 클러스터 데이터소스 정보를 JNDI unbind한다.
전체적인 메커니즘은 클러스터 삭제에서의 설명과 유사하므로 별도로 설명하지 않으므로 해당 절을 참고한다.
7.9. 클러스터 데이터소스 삭제
클러스터 데이터소스도 일반 데이터소스처럼 동적으로 도메인으로부터 삭제될 수 있다. 클러스터 데이터소스가 도메인으로부터 삭제되면 삭제된 클러스터 데이터소스는 그것을 사용하던 서버와 클러스터에서 더 이상 유효하지 않다. 즉, 삭제된 클러스터 데이터소스를 사용하던 서버들은 그 데이터소스 정보를 JNDI unbind한다. 클러스터 데이터소스가 삭제될 때 서버 및 클러스터에 등록된 클러스터 데이터소스가 어떻게 처리되는지 확인하기 위해 cds1을 server1과 cluster1에 등록한다. 이후로는 server1과 cluster1에 cds1이 등록된 것을 가정한다.
본 절에서는 cds1을 domain1으로부터 삭제하는 과정을 설명한다.
콘솔 툴 사용
콘솔 툴에서 remove-cluster-data-source를 수행하면 동적으로 클러스터 데이터소스를 도메인으로부터 삭제할 수 있다. remove-cluster-data-source의 보다 자세한 사용법은 JEUS Reference 안내서의 remove-cluster-data-source를 참고한다.
다음은 remove-cluster-data-source를 수행하여 cds1을 domain1으로부터 삭제하는 예이다.
[MASTER]domain1.adminServer>remove-cluster-data-source -id cds1 Successfully performed the REMOVE operation for cluster data source [cds1] from domain. ================================================================================ +---------------------------------------------------------+--------+-----------+ | resources.dataSource.clusterDs | MODIFY | ACTIVATED | | servers.server.{? name == 'server1' }.dataSources | MODIFY | ACTIVATED | | clusters.cluster.{? name == 'cluster1' }.dataSources | MODIFY | ACTIVATED | +---------------------------------------------------------+--------+-----------+ ================================================================================ Check the results using "remove-cluster-data-source"
위의 결과를 보면 remove-cluster-data-source를 수행하여 cds1를 삭제할 때 cds1이 등록되어 있던 server1과 cluter1에도 어떠한 변화가 생겼음을 짐작할 수 있다. 위의 결과는 cds1이 domain1에서 삭제되는 동시에 server1과 cluster1에 등록되었던 cds1 정보도 제거됨을 표시하고 있다.
이와 같이 동적으로 설정을 변경하는 명령어를 수행하면 그와 연관되어 발생하는 모든 설정 변경의 런타임 반영 여부를 확인할 수 있다. 동적 설정 변경 명령어의 보다 자세한 사용법은 JEUS Domain 안내서의 도메인 설정변경을 참고한다.
cds1이 삭제된 것은 위의 결과 메시지를 통해서 알 수 있듯이 remove-cluster-data-source를 수행하여 확인할 수 있다.
[MASTER]domain1.adminServer>remove-cluster-data-source Shows the current configuration. Data sources in domain ==================================================================== +------+-----------------------------------------------------------+ | ds1 | common data source | | ds2 | common data source | +------+-----------------------------------------------------------+ ====================================================================
이제 cds1이 domain1으로부터 삭제되었으므로 스스로 cds1을 등록하여 사용하던 server1과 cluster1에 속하여 cluster1에 등록되어 있던 cds1를 사용할 수 있었던 server2와 server3는 더 이상 cds1을 사용할 수 없다. 이는 곧 server1, server2, server3 각각의 JNDI Repository로부 cds1이 JNDI unbind되었음을 의미한다.
jndilist를 수행하여 server1의 JNDI Repository를 확인하면 cds1은 더 이상 JNDI bind되어 있지 않음을 확인할 수 있다.
[MASTER]domain1.adminServer>jndilist -server server1 The JNDI list on the server1 List of the context / ================================================================================ +-------------+------------------------------------------------+---------------+ | Name | Value | Local Binding | +-------------+------------------------------------------------+---------------+ | ds1 | jeus.jdbc.info.JDBCBindInfo | true | | ds2 | jeus.jdbc.info.JDBCBindInfo | true | | JEUSMQ_DLQ | jeus.jms.common.destination.JeusQueue | false | | mgmt | jeus.jndi.JNSContext | false | +-------------+------------------------------------------------+---------------+ ================================================================================
jndilist를 수행하여 cluster1에 속한 server2의 JNDI Repository를 확인해 보아도 cds1은 더 이상 JNDI bind 되어있지 않음을 알 수 있다.
[MASTER]domain1.adminServer>jndilist -server server2 The JNDI list on the server2 List of the context / ================================================================================ +-------------+------------------------------------------------+---------------+ | Name | Value | Local Binding | +-------------+------------------------------------------------+---------------+ | ds1 | jeus.jdbc.info.JDBCBindInfo | true | | ds2 | jeus.jdbc.info.JDBCBindInfo | true | | JEUSMQ_DLQ | jeus.jms.common.destination.JeusQueue | false | | mgmt | jeus.jndi.JNSContext | false | +-------------+------------------------------------------------+---------------+ ================================================================================
7.10. 클러스터 데이터소스 설정 변경
지금까지는 클러스터 데이터소스, 서버, 클러스터를 추가/삭제할 때 어떻게 데이터소스의 관리가 이루어지는지 살펴보았다. 이제는 클러스터 데이터소스 자체의 설정 변경에 대해서 알아보자. 클러스터 데이터소스의 설정은 모두 동적 변경이 가능한데 그 중 클러스터 데이터소스에 묶인 컴포넌트 데이터소스 변경을 예로 들도록 하겠다.
우선 현재 클러스터 데이터소스가 도메인에 없는 상태이므로 add-cluster-data-source를 수행하여 컴포넌트 데이터소스를 ds1, ds2로 하는 클러스터 데이터소스 cds1을 domain1에 추가한다. 이후로는 ds1, ds2를 컴포넌트 데이터소스로 갖는 cds1이 domain1에 추가된 것을 가정한다.
본 절에서는 cds1의 컴포넌트 데이터소스 목록에서 ds2를 삭제하는 과정을 설명한다.
콘솔 툴 사용
콘솔 툴에서 modify-cluster-data-source를 수행하면 동적으로 클러스터 데이터소스 설정을 변경할 수 있다. help를 수행하거나 JEUS Reference 안내서의 modify-cluster-data-source를 참고하면 modify-cluster-data-source를 통하여 변경할 수 있는 모든 설정들을 옵션들의 이름으로 유추하여 확인할 수 있다. 동적 변경이 가능한 설정과 관련된 옵션에는 태그를 붙여두었으므로 이를 통해 어떤 설정이 동적으로 변경 가능한지도 알 수 있다.
다음은 modify-cluster-data-source를 수행하여 ds2를 cds1의 컴포넌트 데이터소스 목록에서 삭제하는 예이다.
[MASTER]domain1.adminServer>modify-cluster-data-source -id cds1 -cds ds1 Successfully performed the MODIFY operation for configuration of the cluster data source [cds1]. Check the results using "modify-cluster-data-source -id cds1"
cds1 컴포넌트 데이터소스 목록에서 ds2가 삭제되었음은 'modify-cluster-data-source -id cds1'을 수행하여 기타 다른 설정값들과 함께 확인할 수 있다.
[MASTER]domain1.adminServer>modify-cluster-data-source -id cds1 Shows the current configuration. configuration of the cluster data source [cds1] ===================================================================== +-----------------------------------------------------------+-------+ | id | cds1 | | export-name | cds1 | | load-balance | false | | is-pre-conn | false | | use-failback | true | | component-data-sources | ds1 | +-----------------------------------------------------------+-------+ =====================================================================
7.11. 클러스터 데이터소스 설정 확인
JEUS 7부터는 설정 파일을 열어 사용자가 직접 수정한 설정에 대해서 책임지지 않는다. 설정 파일을 열어서 설정을 확인하는 것은 그러한 변경과는 관련이 없으나 되도록이면 설정 파일에 직접 접근하는 것을 권장하지 않는다. 이를 위해 클러스터 데이터소스의 설정을 명령어를 통해 확인할 수 있도록 지원한다.
본 절에서는 콘솔 툴을 사용해서 클러스터 데이터소스 설정을 확인하는 방법을 설명한다.
콘솔 툴 사용
콘솔 툴에서 list-cluster-data-sources 명령어를 수행하면 도메인에 존재하는 모든 클러스터 데이터소스의 목록이 조회된다.
다음은 list-cluster-data-sources의 수행하여 도메인에 존재하는 모든 클러스터 데이터소스 목록을 확인하는 예이다.
[MASTER]domain1.adminServer>list-cluster-data-sources The list of cluster data sources ================================================================================ +--------------------+-----------------------+---------------------------------+ | Data Source ID | JNDI Export Name | Component Data Sources | +--------------------+-----------------------+---------------------------------+ | cds1 | cds1 | [ds1] | +--------------------+-----------------------+---------------------------------+ ================================================================================
만약 특정 클러스터 데이터소스의 ID를 id 옵션값으로 입력하면 그 클러스터 데이터소스의 전체 설정을 상세히 보여준다. 다음은 list-cluster-data-sources를 수행하여 cds1의 상세 설정을 확인하는 예이다.
[MASTER]domain1.adminServer>list-cluster-data-sources -id cds1 The configuration of cluster data source [cds1] ================================================================================ +------------------------------------------+-----------------------------------+ | Configuration Name | Configuration Value | +------------------------------------------+-----------------------------------+ | id | cds1 | | export-name | cds1 | | load-balance | false | | is-pre-conn | false | | use-failback | true | | component-data-sources | [ds1] | +------------------------------------------+-----------------------------------+ ================================================================================
8. JDBC Connection Pool 모니터링
본 절에서는 서버에 존재하는 Connection Pool의 모니터링에 대해 예시를 들어 설명한다. 보다 나은 이해를 위해서는 JEUS 도메인 구조와 도메인에서의 데이터소스 및 Connection Pool 관리 구조 등에 대한 이해가 필요하다. JEUS 도메인 구조에 대해서는 JEUS Domain 안내서의 구성요소를 참고하고, 도메인에서의 데이터소스 및 Connection Pool 관리 구조는 데이터소스 및 Connection Pool 관리를 참고한다.
JDBC Connection Pool 모니터링은 콘솔 툴을 통해서 수행될 수 있으므로 본 절에서는 두 가지 방법 모두에 대해서 함께 설명한다. 콘솔 툴을 통한 방법을 설명할 때는 편의상 축약된 명령어 및 옵션의 이름을 사용한다. 축약된 명령어 및 옵션의 이름과 명령어의 세부 사용 방법은 콘솔 툴에서 명령어 이름을 인자로 help를 수행하거나 JEUS Reference 안내서의 Connection Pool 제어 및 모니터링 명령어를 참고하면 확인할 수 있다.
설명을 위해 필요한 몇 가지 사전 작업을 수행한다. 우선 domain1이라는 이름의 도메인과 adminServer라는 이름의 MASTER를 생성한다. MASTER를 기동한 후 각각 server1, server2라는 이름을 갖는 MS 두 개를 domain1에 추가하고 이들 또한 기동한다. 또한 각각 ds1, ds2라는 데이터소스 ID를 갖는 데이터소스를 domain1에 추가한 후 server1에는 ds1과 ds2 모두를 등록하고 server2에는 ds1만 등록하도록 한다. 마지막으로 server1과 server2에 ds1의 Connection Pool을 각각 생성한다.
도메인 및 서버 관련 설정 방법은 JEUS Domain 안내서의 도메인 생성 및 JEUS Server 안내서의 JEUS 설정을, 데이터소스 관련 설정 방법은 데이터소스 관련 설정 동적 변경을 참고한다. Connection Pool 생성 방법은 JDBC Connection Pool 제어를 참고한다. 이후로는 앞서 언급한 사전 작업이 모두 완료되었음을 가정한다.
데이터소스가 등록되는 대상은 궁극적으로 서버이다. 서버 자체적으로 데이터소스를 등록하는 경우는 물론이고 클러스터가 데이터소스를 등록한 경우에도 클러스터에 등록된 데이터소스는 실질적으로 클러스터에 속한 서버들에 의미가 있다. 클러스터는 서버를 묶어주는 논리적 그룹일 뿐 실제로 데이터소스를 이용해 Connection Pool을 생성하여 사용하는 주체는 서버이기 때문이다. 이와 같은 이유로 Connection Pool의 모니터링 단위는 서버다. |
8.1. JDBC Connection Pool 목록 확인
본 절에서는 콘솔 툴을 사용해서 JDBC Connection Pool 목록을 확인하는 방법에 대해서 설명한다.
콘솔 툴 사용
콘솔 툴에서 connection-pool-info를 수행하면 서버에 존재하는 모든 Connection Pool의 목록을 확인할 수 있다. connection pool-info는 JDBC Connection Pool뿐만 아니라 JCA Connection Pool에 대해서도 동일한 기능을 수행하므로 JDBC Connection Pool에 대해서 사용하려면 -jdbc 옵션을 설정한다. connection-pool-info에 대한 보다 자세한 사용법은 JEUS Reference 안내서의 connection-pool-info를 참고한다.
다음은 connection-pool-info를 수행하여 server1에 존재하는 모든 JDBC Connection Pool의 목록을 확인하는 예이다.
[MASTER]domain1.adminServer>connection-pool-info -server server1 -jdbc The connection pool information on the server [server1]. ================================================================================ +--------+-----+-----+--------+-----+--------+-----+--------+-----+-----+------+ | Connec | Min | Max | Active | Act | Active | Idle| Dispos | Tot | Wait| Enab | | tion | | | Max | ive | Average| | able | al | | led | |Pool ID | | | | | | | | | | | +--------+-----+-----+--------+-----+--------+-----+--------+-----+-----+------+ | ds1 | 2 | 30 | 0 | 0 | 0.0 | 2 | 0 | 2 | fal | true | | | | | | | | | | |se | | +--------+-----+-----+--------+-----+--------+-----+--------+-----+-----+------+ | ds2 * | 2 | 30 | 0 | 0 | 0.0 | 0 | 0 | 0 | fal | false| | | | | | | | | | |se | | +--------+-----+-----+--------+-----+--------+-----+--------+-----+-----+------+ * : has not been created, total = active + idle + disposable ================================================================================
server1이 ds1과 ds2를 모두 등록하고 있으므로 ds1과 ds2의 Connection Pool이 존재하는 것을 확인할 수 있다. 특히 사전 작업의 결과대로 ds1 Connection Pool은 생성된 상태며 ds2 Connection Pool은 생성되지 않은 상태임을 확인할 수 있다.
컬럼은 각각 Connection Pool ID, Connection의 최솟값, Connection의 최댓값, Connection Pool 생성 이후 Active Connection의 최댓값, Active Connection의 개수, 최근 1시간 동안의 Active Connection 개수의 평균, Idle Connection의 개수, Disposable Connection의 개수, Connection의 총 개수, Connection이 부족할 경우의 대기 여부, Connection Pool의 활성화 여부를 표시한다.
다음과 같이 active 옵션을 사용하면 현재 생성된 Connection Pool의 리스트만 확인할 수 있다.
[MASTER]domain1.adminServer>connection-pool-info -server server1 -active -jdbc The connection pool information on the server [server1]. ================================================================================ +--------+-----+-----+--------+-----+--------+-----+--------+-----+-----+------+ | Connec | Min | Max | Active | Act | Active | Idle| Dispos | Tot | Wait| Enab | | tion | | | Max | ive | Average| | able | al | | led | |Pool ID | | | | | | | | | | | +--------+-----+-----+--------+-----+--------+-----+--------+-----+-----+------+ | ds1 | 2 | 30 | 0 | 0 | 0.0 | 2 | 0 | 2 | fal | true | | | | | | | | | | |se | | +--------+-----+-----+--------+-----+--------+-----+--------+-----+-----+------+ * : has not been created, total = active + idle + disposable ================================================================================
또한 jndi 옵션을 사용하면 데이터소스의 JNDI 이름도 함께 표시한다.
[MASTER]domain1.adminServer>connection-pool-info -server server1 -jndi -jdbc The connection pool information on the server [server1]. ================================================================================ +------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ | Connection |JNDI | Min | Max | Act | Act | Act | Idle| Dis | Tot | Wait| Ena | | Pool ID |Expo | | | ive | ive | ive | |posa | al | |bled | | | rt | | | Max | |Aver | | ble | | | | | |Name | | | | | age | | | | | | +------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ | ds1 | ds1 | 2 | 30 | 0 | 0 | 0.0 | 2 | 0 | 2 | fal | true| | | | | | | | | | | |se | | +------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ | ds2 * | ds2 | 2 | 30 | 0 | 0 | 0.0 | 0 | 0 | 0 | fal | fal | | | | | | | | | | | |se |se | +------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ * : has not been created, total = active + idle + disposable ================================================================================
server2에 존재하는 모든 Connection Pool의 목록도 다음과 같이 확인할 수 있다.
[MASTER]domain1.adminServer>connection-pool-info -server server2 -jdbc The connection pool information on the server [server2]. ================================================================================ +--------+-----+-----+--------+-----+--------+-----+--------+-----+-----+------+ | Connec | Min | Max | Active | Act | Active | Idle| Dispos | Tot | Wait| Enab | | tion | | | Max | ive | Average| | able | al | | led | |Pool ID | | | | | | | | | | | +--------+-----+-----+--------+-----+--------+-----+--------+-----+-----+------+ | ds1 | 2 | 30 | 0 | 0 | 0.0 | 0 | 0 | 0 | fal | fal | | | | | | | | | | |se |se | +--------+-----+-----+--------+-----+--------+-----+--------+-----+-----+------+ * : has not been created, total = active + idle + disposable ================================================================================
server2는 ds1만을 등록하고 있으므로 ds1의 Connection Pool만 존재하며 사전 작업의 결과대로 생성된 상태임을 알 수 있다.
8.2. 특정 JDBC Connection Pool의 상세 정보 확인
본 절에서는 콘솔 툴을 사용해서 특정 JDBC Connection Pool의 상세 정보를 확인하는 방법에 대해서 설명한다.
콘솔 툴 사용
콘솔 툴에서 connection-pool-info를 수행하면 서버에 존재하는 특정 Connection Pool의 상세 정보를 확인할 수 있다. connection pool-info는 JDBC Connection Pool뿐만 아니라 JCA Connection Pool에 대해서도 동일한 기능을 수행하므로 JDBC Connection Pool에 대해서 사용하기 원한다면 -jdbc 옵션을 설정한다. connection-pool-info에 대한 보다 자세한 사용법은 JEUS Reference 안내서의 connection-pool-info를 참고한다.
다음은 connection-pool-info를 수행하여 server1에 존재하는 ds1 Connection Pool의 상세 정보를 확인하는 예이다.
[MASTER]domain1.adminServer>connection-pool-info -server server1 -id ds1 -jdbc Information about connections in the server [server1]'s connection pool [ds1]. ================================================================================ +------------------+-------+------------------------------+-----------+--------+ | Connection ID | State | State Time(sec) | Use Count | Type | +------------------+-------+------------------------------+-----------+--------+ | ds1-1 | idle | 965.837 | 0 | pooled | | ds1-2 | idle | 965.806 | 0 | pooled | +------------------+-------+------------------------------+-----------+--------+ ================================================================================
아직 한 번도 사용되지 않은 두 개의 Connection이 965초 정도 idle 상태로 머물러 있음을 확인할 수 있다. 두 Connection은 모두 disposable Connection이 아니다.
다음과 같이 -t 옵션을 사용하면 Connection을 소유한 Thread의 이름도 함께 확인할 수 있다.
[MASTER]domain1.adminServer>connection-pool-info -server server1 -id ds1 -t -jdbc Information about connections in the server [server1]'s connection pool [ds1]. ================================================================================ +---------------+-------+-------------------+-----------+--------+-------------+ | Connection ID | State | State Time(sec) | Use Count | Type | Thread name | +---------------+-------+-------------------+-----------+--------+-------------+ | ds1-1 | active| 1105.954 | 1 | pooled | http-w1 | | ds1-2 | idle | 1105.923 | 0 | pooled | | +---------------+-------+-------------------+-----------+--------+-------------+ ================================================================================
9. JDBC Connection Pool 제어
본 절에서는 서버에 존재하는 Connection Pool의 제어에 대해 예를 들어 설명한다. 보다 나은 이해를 위해서는 JEUS 도메인 구조와 도메인에서의 데이터소스 및 Connection Pool 관리 구조 등에 대한 이해가 필요하다. JEUS 도메인 구조에 대해서는 JEUS Domain 안내서의 구성요소를 참고하도록 하고, 도메인에서의 데이터소스 및 Connection Pool 관리 구조는 데이터소스 및 Connection Pool 관리를 참고한다.
JDBC Connection Pool 제어는 콘솔 툴을 통해서 수행될 수 있으므로 본 절에서는 두 가지 방법 모두에 대해서 함께 설명한다.
설명을 위해 필요한 몇 가지 사전 작업을 수행한다. 우선 domain1이라는 이름의 도메인과 adminServer라는 이름의 MASTER를 생성한다. MASTER를 기동한 후 각각 server1, server2라는 이름을 갖는 MS 두 개를 domain1에 추가하고 이들 또한 기동한다. 또한 각각 ds1, ds2라는 데이터소스 ID를 갖는 데이터소스를 domain1에 추가한 후 server1, server2 각각에 ds1과 ds2 모두를 등록하도록 한다. 도메인 및 서버 관련 설정 방법은 JEUS Domain 안내서의 도메인 생성 및 JEUS Server 안내서의 JEUS 설정을 참고하고, 데이터소스 관련 설정 방법은 데이터소스 관련 설정 동적 변경을 참고한다.
Connection Pool 제어 후의 결과는 별도로 예를 들어 설명하지 않으므로 JDBC Connection Pool 모니터링을 참고하여 결과를 확인한다. |
9.1. Connection Pool 생성
본 절에서는 콘솔 툴을 사용해서 Connection Pool을 생성하는 방법에 대해서 설명한다.
콘솔 툴 사용
콘솔 툴에서 create-connection-pool을 수행하면 서버에 데이터소스의 Connection Pool을 생성할 수 있다. create-connection-pool에 대한 보다 자세한 사용법은 JEUS Reference 안내서의 create-connection-pool을 참고한다.
다음은 create-connection-pool을 수행하여 server1에 ds1 Connection Pool을 생성하는 예이다.
[MASTER]domain1.adminServer>create-connection-pool -server server1 -id ds1 Servers that successfully created a connection pool : server1 Servers that failed to create a connection pool : none.
server 옵션값을 명시하지 않으면 데이터소스가 등록된 모든 서버를 대상으로 Connection Pool이 생성된다.
다음은 create-connection-pool을 수행하여 ds2가 등록된 server1, server2 각각에 ds2 Connection Pool을 생성하는 예이다.
[MASTER]domain1.adminServer>create-connection-pool -id ds2 Servers that successfully created a connection pool : server1, server2 Servers that failed to create a connection pool : none.
control-connection-pool을 수행해도 JDBC Connection Pool을 생성할 수 있다. control-connection-pool에 대한 보다 자세한 사용법은 JEUS Reference 안내서의 control-connection-pool을 참고한다.
다음은 control-connection-pool을 수행하여 server1에 ds1 Connection Pool을 생성하는 예이다.
[MASTER]domain1.adminServer>control-connection-pool -server server1 -id ds1 -create Servers that successfully created a connection pool : server1 Servers that failed to create a connection pool : none.
9.2. Connection Pool 비활성화
본 절에서는 콘솔 툴을 사용해서 Connection Pool 비활성화하는 방법에 대해서 설명한다.
콘솔 툴 사용
콘솔 툴에서 disable-connection-pool을 수행하면 서버에 존재하는 Connection Pool을 비활성화할 수 있다. disable-connection-pool에 대한 보다 자세한 사용법은 JEUS Reference 안내서의 disable-connection-pool을 참고한다.
다음은 disable-connection-pool을 수행하여 server1에 생성된 ds1 Connection Pool을 비활성화하는 예이다.
[MASTER]domain1.adminServer>disable-connection-pool -server server1 -id ds1 Servers that successfully disabled a connection pool : server1 Servers that failed to disable a connection pool : none.
server 옵션값을 명시하지 않으면 데이터소스가 등록된 모든 서버를 대상으로 Connection Pool 비활성화가 시도된다.
다음은 disable-connection-pool을 수행하여 ds2가 등록된 server1, server2 각각에 대해 ds2 Connection Pool 비활성화를 수행하는 예이다.
[MASTER]domain1.adminServer>disable-connection-pool -id ds2 Servers that successfully disabled a connection pool : server1, server2 Servers that failed to disable a connection pool : none.
control-connection-pool을 수행해도 JDBC Connection Pool을 비활성화할 수 있다. control-connection-pool에 대한 보다 자세한 사용법은 JEUS Reference 안내서의 control-connection-pool을 참고한다.
다음은 control-connection-pool을 수행하여 server1에 생성된 ds1 Connection Pool을 비활성화하는 예이다.
[MASTER]domain1.adminServer>control-connection-pool -server server1 -id ds1 -disable Servers that successfully disabled a connection pool : server1 Servers that failed to disable a connection pool : none.
9.3. Connection Pool 활성화
본 절에서는 콘솔 툴을 사용해서 Connection Pool 활성화하는 방법에 대해서 설명한다.
콘솔 툴 사용
콘솔 툴에서 enable-connection-pool 명령어를 수행하면 서버에 존재하는 Connection Pool을 활성화할 수 있다. enable-connection-pool에 대한 보다 자세한 사용법은 JEUS Reference 안내서의 enable-connection-pool을 참고한다.
다음은 enable-connection-pool을 수행하여 server1에 생성된 ds1 Connection Pool을 활성화하는 예이다.
[MASTER]domain1.adminServer>enable-connection-pool -server server1 -id ds1 Servers that successfully enabled a connection pool : server1 Servers that failed to enable a connection pool : none.
server 옵션값을 명시하지 않으면 데이터소스가 등록된 모든 서버를 대상으로 Connection Pool 활성화가 시도된다.
다음은 enable-connection-pool을 수행하여 ds2가 등록된 server1, server2 각각에 대해 ds2 Connection Pool 활성화를 수행하는 예이다.
[MASTER]domain1.adminServer>enable-connection-pool -id ds2 Servers that successfully enabled a connection pool : server1, server2 Servers that failed to enable a connection pool : none.
control-connection-pool을 수행해도 JDBC Connection Pool을 활성화할 수 있다. control-connection-pool에 대한 보다 자세한 사용법은 JEUS Reference 안내서의 control-connection-pool을 참고한다.
다음은 control-connection-pool을 수행하여 server1에 생성된 ds1 Connection Pool을 활성화하는 예이다.
[MASTER]domain1.adminServer>control-connection-pool -server server1 -id ds1 -enable Servers that successfully enabled a connection pool : server1 Servers that failed to enable a connection pool : none.
9.4. Connection Pool의 Connection 교체
본 절에서는 콘솔 툴을 사용해서 Connection Pool의 Connection을 교체하는 방법에 대해서 설명한다.
콘솔 툴 사용
콘솔 툴에서 refresh-connection-pool 명령어를 수행하면 서버에 존재하는 Connection Pool의 Connection들을 새로운 Connection으로 교체할 수 있다. refresh-connection-pool에 대한 보다 자세한 사용법은 JEUS Reference 안내서의 refresh-connection-pool을 참고한다.
다음은 refresh-connection-pool을 수행하여 server1에 생성된 ds1 Connection Pool의 Connection들을 새로운 Connection으로 교체하는 예이다.
[MASTER]domain1.adminServer>refresh-connection-pool -server server1 -id ds1 Servers that successfully refreshed a connection pool : server1 Servers that failed to refresh a connection pool : none.
server 옵션값을 명시하지 않으면 데이터소스가 등록된 모든 서버를 대상으로 Connection Pool의 Connection 교체가 시도된다.
다음은 refresh-connection-pool을 수행하여 ds2가 등록된 server1, server2 각각에 대해 ds2 Connection Pool의 Connection들을 새로운 Connection으로 교체하는 예이다.
[MASTER]domain1.adminServer>refresh-connection-pool -id ds2 Servers that successfully refreshed a connection pool : server1, server2 Servers that failed to refresh a connection pool : none.
control-connection-pool을 수행해도 JDBC Connection Pool의 Connection들을 새로운 Connection으로 교체할 수 있다. control-connection-pool에 대한 보다 자세한 사용법은 JEUS Reference 안내서의 control-connection-pool을 참고한다.
다음은 control-connection-pool을 수행하여 server1에 생성된 ds1 Connection Pool의 Connection들을 새로운 Connection으로 교체하는 예이다.
[MASTER]domain1.adminServer>control-connection-pool -server server1 -id ds1 -refresh Servers that successfully refreshed a connection pool : server1 Servers that failed to refresh a connection pool : none.
9.5. Connection Pool의 Connection 개수 최소화
본 절에서는 콘솔 툴을 사용해서 Connection Pool의 Connection 개수를 최소화하는 방법에 대해서 설명한다.
콘솔 툴 사용
콘솔 툴에서 shrink-connection-pool 명령어를 수행하면 서버에 존재하는 Connection Pool의 Connection 개수를 설정된 Connection 최솟값으로 조정할 수 있다. shrink-connection-pool에 대한 보다 자세한 사용법은 JEUS Reference 안내서의 shrink-connection-pool을 참고한다.
다음은 shrink-connection-pool을 수행하여 server1에 생성된 ds1 Connection Pool의 Connection 개수를 설정된 Connection 최솟값으로 조정하는 예이다.
[MASTER]domain1.adminServer>shrink-connection-pool -server server1 -id ds1 Servers that successfully shrank a connection pool : server1 Servers that failed to shrink a connection pool : none.
server 옵션값을 명시하지 않으면 데이터소스가 등록된 모든 서버를 대상으로 Connection Pool의 Connection 개수 조정이 시도된다.
다음은 shrink-connection-pool을 수행하여 ds2가 등록된 server1, server2 각각에 대해 ds2 Connection Pool의 Connection 개수를 설정된 Connection 최솟값으로 조정하는 예이다.
[MASTER]domain1.adminServer>shrink-connection-pool -id ds2 Servers that successfully shrank a connection pool : server1, server2 Servers that failed to shrink a connection pool : none.
control-connection-pool을 수행해도 JDBC Connection Pool의 Connection 개수를 설정된 Connection 최솟값으로 조정할 수 있다. control-connection-pool에 대한 보다 자세한 사용법은 JEUS Reference 안내서의 control-connection-pool을 참고한다.
다음은 control-connection-pool을 수행하여 server1에 생성된 ds1 Connection Pool의 Connection 개수를 설정된 Connection 최솟값으로 조정하는 예이다.
[MASTER]domain1.adminServer>control-connection-pool -server server1 -id ds1 -shrink Servers that successfully shrank a connection pool : server1 Servers that failed to shrink a connection pool : none.
9.6. Connection Pool의 Connection 연결 반환(Return Connection)
본 절에서는 콘솔 툴을 사용해서 Connection Pool의 Connection 연결 반환(Return Connection)을 하는 방법에 대해서 설명한다.
애플리케이션에서 데이터소스에 getConnection 요청을 한 뒤 마지막에 Connection을 close해주지 않으면 해당 Connection은 Data Source가 AutoClose 설정이 되어있지 않는 한 계속 Active 상태로 남아있게 된다. 이러한 Connection Leak이 발생하였을 때 연결 반환(Return Connection) 기능을 이용하여 Leak이 발생한 Connection을 Connection Pool에 반환할 수 있다.
콘솔 툴 사용
콘솔 툴에서 return-connection 명령어를 수행하면 서버에 존재하는 Connection Pool의 Active 상태인 Connection을 Connection Pool로 연결 반환(Return Connection)할 수 있다. return-connection에 대한 보다 자세한 사용법은 JEUS Reference 안내서의 return-connection을 참고한다.
다음은 return-connection을 수행하여 server1에 생성된 ds1 Connection Pool의 ds1-1 Connection을 Active 상태에서 Idle 상태로 Connection Pool에 반환하는 예이다. connection-pool-info 명령어를 사용하여 ds1-1 Connection이 현재 Leak이 발생하여 Active 상태로 머물고 있는지 확인 할 수 있고, 해당 Connection에 대해 return-connection 명령어를 사용한다.
[MASTER]domain1.adminServer>connection-pool-info -server server1 -id ds1 Information about connections in the server [server1]'s connection pool [ds1]. ================================================================================ +------------------+--------+---------------------------+-------------+--------+ | Connection ID | State | State Time(sec) | Use Count | Type | +------------------+--------+---------------------------+-------------+--------+ | ds1-2 | idle | 22.311 | 0 | pooled | | ds1-1 | active | 22.289 | 0 | pooled | +------------------+--------+---------------------------+-------------+--------+ ================================================================================ [MASTER]domain1.adminServer>return-connection -server server1 -cid ds1-1 Successfully returned the connections to the connection pool.
같은 Connection Pool일 경우 cid 옵션에 여러 개의 Connection을 쉼표로 구분하여 한번에 연결 반환 (Return Connection)할 수도 있고, cpid 옵션을 이용하여 하나의 Connection Pool에 존재하는 모든 Connection들을 반환 시도할 수 있다.
다음은 return-connection을 수행하여 Connection Pool ds1에 존재하는 모든 Active Connection들을 Connection Pool에 반환하는 예이다.
[MASTER]domain1.adminServer>return-connection -server server1 -cpid ds1 Successfully returned the connections to the connection pool.
9.7. Connection Pool의 Connection 강제 끊기(Destroy Connection)
본 절에서는 콘솔 툴을 사용해서 Connection Pool의 Connection을 강제로 끊는 방법에 대해서 설명한다.
애플리케이션에서 데이터소스에 getConnection 요청을 하여서 Active 상태로 있는 Connection이 문제가 있다고 판단되면 강제 끊기(Destroy Connection) 기능을 이용하여 문제가 있다고 판단되는 Connection을 강제로 끊을 수 있다. 단, 이 기능은 실제로 물리적 연결을 강제로 끊는 것이므로 사용에 주의를 요한다.
콘솔 툴 사용
콘솔 툴에서 destroy-connection 명령어를 수행하면 서버에 존재하는 Connection Pool의 Active 상태인 Connection의 연결을 강제로 끊을 수 있다. destroy-connection에 대한 보다 자세한 사용법은 JEUS Reference 안내서의 destroy-connection을 참고한다.
다음은 destroy-connection을 수행하여 server1에 생성된 ds1 Connection Pool의 ds1-1 Connection을 Active 상태에서 강제로 연결 끊는 예이다. connection-pool-info 명령어를 사용하여 ds1-1 Connection이 현재 Active 상태로 머물고 있는지 확인 할 수 있고, 해당 Connection에 대해 destroy-connection 명령어를 사용한다.
[MASTER]domain1.adminServer>connection-pool-info -server server1 -id ds1 Information about connections in the server [server1]'s connection pool [ds1]. ================================================================================ +------------------+--------+---------------------------+-------------+--------+ | Connection ID | State | State Time(sec) | Use Count | Type | +------------------+--------+---------------------------+-------------+--------+ | ds1-2 | idle | 22.311 | 0 | pooled | | ds1-1 | active | 22.289 | 0 | pooled | +------------------+--------+---------------------------+-------------+--------+ ================================================================================ [MASTER]domain1.adminServer>destroy-connection -server server1 -cid ds1-1 Successfully destroyed the connections from the connection pool.
같은 Connection Pool일 경우 cid 옵션에 여러 개의 Connection을 쉼표로 구분하여 한번에 연결을 강제로 끊을 수도 있고, cpid 옵션을 이용하여 하나의 Connection Pool에 존재하는 모든 Connection들의 연결을 강제로 끊도록 시도할 수 있다.
다음은 destroy-connection을 수행하여 Connection Pool ds1에 존재하는 모든 Active Connection들을 강제로 끊는 예이다.
[MASTER]domain1.adminServer>destroy-connection -server server1 -cpid ds1 Successfully destroyed the connections from the connection pool.
10. JEUS JDBC 프로그래밍
본 절에서는 JDBC 애플리케이션 프로그래밍 규칙에 대해 간략히 설명한다.
10.1. 데이터소스로부터 Connection 얻기
다음의 코드는 데이터소스를 사용하여 Connection을 얻는 방법에 대한 예이다.
Context ctx = new InitialContext(); DataSource ds = (DataSource) ctx.lookup("ds1"); Connection con = ds.getConnection(); Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery("select * from test"); ... con.close();
Connection을 사용한 후에는 반드시 닫아야 한다. |
10.2. 트랜잭션 프로그래밍 규칙
JEUS는 트랜잭션 프로그래밍을 위한 표준 단계를 정의한다. UserTransaction를 사용하는 모든 애플리케이션은 표준 단계들을 따라야 한다.
-
트랜잭션을 시작한다.
-
DB Connection을 얻어 온다.
-
트랜잭션의 나머지를 코딩한다.
만약 다른 트랜잭션 처리를 원한다면 반드시 새로운 Connection을 다시 얻어야 한다. |
10.3. JDBC 드라이버의 Connection 구현체 인스턴스 얻기
JEUS에서는 애플리케이션에 Connection을 넘겨줄 때 Connection의 상태 관리를 위하여 래퍼를 사용하게 된다. 그러나 Oracle의 CLOB, XMLType 등은 JDBC 드라이버의 Connection 구현체 인스턴스를 직접적으로 필요로 하기 때문에 드라이버 내부적으로 클래스 캐스팅을 하다가 ClassCastException이 발생한다. 이는 JEUS뿐만 아니라 대부분의 WAS 제품에서 발생할 수 있는 문제로 애플리케이션 작성자는 WAS에서 넘어오는 Connection이 드라이버의 Connection 구현체 인스턴스일 것이라고 가정하여 애플리케이션 코드를 작성하면 안 된다. 하지만 이를 우회적으로 피할 수 있는 방법이 있다.
애플리케이션에서는 다음과 같은 방법으로 드라이버의 Connection 구현체 인스턴스를 얻을 수 있다.
import java.sql.Connection; import java.sql.DatabaseMetaData; ... Connection conn = datasource.getConnection(); DatabaseMetaData metaData = conn.getMetaData(); OracleConnection oraConn = (OracleConnection)metaData.getConnection();
10.4. Standalone 클라이언트에서의 Connection Pool
Standalone 클라이언트에서 JEUS에 등록된 데이터소스를 Lookup하면 해당 데이터소스의 정보를 JEUS로부터 얻어 자신의 JVM에 Connection Pool을 구성할 수 있다. 이때 Standalone 클라이언트는 clientcontainer.jar 또는 jclient.jar를 클래스 패스에 추가해야 한다.
이러한 방식은 Standalone 클라이언트에서 JNDI Lookup 방식으로 편리하게 DB에 접근할 수 있다는 장점이 있으나 DB 입장에서는 WAS 외에 JDBC 드라이버로 접근하는 클라이언트가 증가하는 것이고 클라이언트가 특별히 DB Connection을 효율적으로 관리할 필요가 있는 것이 아니라면 클라이언트에 Connection Pool을 구성하는 것은 불필요한 자원 낭비가 될 수 있다. 따라서 실제 서비스를 구현할 때는 이 방식의 사용을 권장하지 않는다.
JEUS 서버에 구성된 Connection Pool에서 Connection을 가져와서 사용하는 것이 아니다. 만약 그렇게 하고 싶다면 Connection을 사용하는 로직을 EJB로 구현해서 JEUS에 deploy하고 EJB를 찾아서(Lookup) 사용해야 한다. |
11. 글로벌 트랜잭션(XA)과 Connection Sharing
Connection Sharing(커넥션 공유)은 같은 트랜잭션 내에서는 하나의 리소스에 대해 항상 하나의 Connection만 사용하는 것을 보장한다는 개념으로 JCA 표준에 언급되어 있다. JDBC 관점에서의 리소스는 대부분 DB(또는 데이터소스)이다. JEUS는 특별한 설정 없어도 기본적으로 XA 데이터소스 및 XA 에뮬레이션 기능을 사용하는 Connection Pool 데이터소스에 대해 Connection Sharing을 제공한다.
ProFrame과 같은 Application Framework에서는 같은 트랜잭션 내에서 하나의 데이터소스에 대해 여러 번 Connection 요청을 하는 경우가 많으므로 Connection Sharing을 사용하는 것이 바람직하다. 그렇지 않으면 하나의 데이터소스에 대해 여러 개의 물리적 Connection이 트랜잭션에 참여하게 된다. 이는 DB에 불필요하게 많은 트랜잭션 Lock을 관리해야 하는 부담을 주게 되어 트랜잭션 성능이 전체적으로 떨어질 수 있다.
만약 Connection Sharing을 사용하고 싶지 않을 때는 XA 데이터소스를 사용하는 Jakarta EE 컴포넌트 설정 파일(web.xml, ejb-jar.xml 등)을 다음과 같이 작성한다. <res-ref-name>는 데이터소스의 JNDI 이름을 입력한다.
<resource-ref> <res-ref-name>jdbc/xads</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-sharing-scope>Unshareable</res-sharing-scope> </resource-ref>
아무런 설정을 하지 않으면 기본적으로 <res-sharing-scope>가 Shareable이므로 Servlet이나 EJB에서 항상 Connection Sharing을 사용한다. 단, XA 에뮬레이션 기능을 사용하는 Connection Pool 데이터소스는 항상 Connection을 공유해야 하기 때문에 Unshareable로 설정하면 에러(java.sql.SQLException)가 발생한다.
12. 여러 사용자에 대한 Connection Pooling 서비스 지원
JEUS는 데이터소스 설정상 명시된 기본 사용자에 대해서만 Connection Pooling 서비스를 지원해왔다. 만약 기본 사용자가 아닌 사용자 정보로 Connection을 요청할 경우에는 해당 Connection을 무조건 일회용(disposable) Connection으로 다룬다. 일회용 Connection은 이름 그대로 Connection 요청이 있을 때마다 생성됐다가 사용 후 바로 Connection Pool로부터 제거되므로 그에 대한 요청이 많을 경우 Connection Pooling 서비스에는 상당한 부담이 될 수 있다.
이를 위해 여러 사용자에 대하여 Connection Pooling 서비스를 지원한다. 이는 하나의 Connection Pool이 외부에는 투명하게 사용자별로 다시 나뉘어 관리되는 방식이므로 클라이언트는 기존의 방식과 비교하여 아무런 차이 없이 Connection Pooling 서비스를 이용할 수 있다. 즉, Connection Pool에 존재하는 Connection들은 서로 사용자 정보가 달라도 Connection Pool의 전체적인 설정과 운영 정책은 공통적으로 따르게 되는 것이다. 그러므로 다수의 사용자별 Connection을 빈번하게 사용하게 되는 경우에도 일회용 Connection을 생성해야 하는 부담 없이 보다 효율적으로 Connection Pooling 서비스를 이용할 수 있다.