닷넷 시스템에서 리소스, DB 연결 모니터링

CPU와 메모리 등의 시스템 자원 및 DB 모니터링 하는 방법을 설명한다.

CPU 모니터링

제니퍼 에이전트를 통해서 애플리케이션이 동작하는 하드웨어의 시스템 CPU 사용률과 해당 애플리케이션이 사용하는 프로세스 CPU 사용률을 모니터링 할 수 있다. 그리고 특정 트랜잭션의 처리 과정에서 사용한 트랜잭션 CPU 점유 시간도 모니터링 할 수 있다. 또한 제니퍼 에이전트의 설치와 상관없이 WMOND를 통해서 임의의 하드웨어의 CPU 개수당 CPU 사용률도 모니터링 할 수 있다.

시스템 CPU 사용률과 프로세스 CPU 사용률

시스템 CPU 사용률은 시스템의 전체 CPU 사용률을 의미하고, 프로세스 CPU 사용률은 제니퍼 에이전트를 설치한 애플리케이션이 사용하는 CPU 사용률을 의미한다.

시스템 CPU 사용률과 프로세스 CPU 사용률은 제니퍼 에이전트가 수집하는 일반 성능 데이터로 실시간 값을 이퀄라이저 차트와 런타임 라인 차트를 통해서 확인할 수 있다.

실시간 시스템 CPU 사용률 차트

그런데 CPU 사용률은 CPU 사용 영역별로 구분되고, 이퀄라이저 차트는 CPU 사용률을 영역별로 색상을 구분하여 표시한다. 다음은 CPU 사용 영역에 대한 설명이다.

CPU 사용 영역

CPU 사용 영역

설명

WAIT

(닷넷 에이전트에서는 사용 안함)

NICE

(닷넷 에이전트에서는 사용 안함)

USER

사용자 수준(애플리케이션)에서 사용하는 CPU 사용률을 의미한다.

SYS

시스템 수준(커널)에서 사용하는 CPU 사용률을 의미한다.

이퀄라이저 차트는 프로세스 CPU 사용률과 에이전트가 수집한 CPU 개수당 CPU 사용률도 CPU 사용 영역별로 색상을 구분하여 표시한다.

또한 시스템 CPU 사용률과 자바 프로세스 CPU 사용률에 대한 5분 평균 값은 PERF_X_01~31 테이블의 SYS_CPU 칼럼과 JVM_CPU 칼럼에 저장되고, 특정 날짜의 CPU 사용률 변화 추이는 라인 차트를 통해서 확인할 수 있다.

금일 시스템 CPU 사용률

트랜잭션 CPU 점유 시간

트랜잭션 CPU 점유 시간은 트랜잭션이 수행되는 과정에서 사용한 CPU 사용 시간을 의미한다. 이는 애플리케이션 처리 현황 통계 데이터와 X-View 프로파일 데이터로 수집된다.

그리고 tpmC를 통해서 트랜잭션 CPU 점유 시간을 하드웨어 별로 객관적으로 비교할 수 있다. tmpC는 TPC(Transaction Processing Performance Council, http://www.tpc.org)의 TPC-C 벤치마크 시나리오에 대한 1분당 최대 처리 건수를 나타내는 수치로써, 하드웨어(주로 CPU)의 성능을 측정하는 대표적인 방법이다.

하드웨어의 CPU 처리 용량이 다르기 때문에 트랜잭션 CPU 점유 시간만으로는 해당 트랜잭션이 성능에 미치는 영향을 객관적으로 파악할 수 없다. 예를 들어, CPU 처리 용량이 큰 하드웨어에서 처리된 트랜잭션 A의 CPU 점유 시간이 CPU 처리 용량이 작은 하드웨어에서 처리된 트랜잭션 B의 CPU 점유 시간보다 작은 경우에도 성능에 미치는 절대적인 영향은 트랜잭션 A가 더 높을 수도 있다. 즉 트랜잭션 A를 CPU 처리 용량이 작은 하드웨어에서 처리하면 트랜잭션 B보다 CPU 점유 시간이 클 수 있다는 것이다.

따라서 tpmC로 하드웨어의 CPU 처리 용량 변수를 통제한 상태에서 트랜잭션이 성능에 미치는 영향을 파악해야 한다.

이를 위해서 제니퍼 에이전트의 approximate_tpmc_on_this_system 옵션으로 제니퍼 에이전트를 설치한 해당 하드웨어의 tpmC 값을 설정하도록 한다.

approximate_tpmc_on_this_system = 30000

CPU 모니터링과 경보 발령

시스템 CPU 사용률과 프로세스 CPU 사용률이 임계치를 초과하면 제니퍼 서버는 경보를 발령한다. 자세한 사항은 경보와 예외 모니터링을 참조한다.

메모리 모니터링

제니퍼 에이전트를 통해서 자바 애플리케이션이 동작하는 하드웨어의 시스템 메모리 사용량과 해당 자바 애플리케이션이 사용하는 자바 프로세스 메모리 사용량을 모니터링할 수 있다. 그리고 자바 애플리케이션의 자바 힙 메모리 전체와 자바 힙 메모리 사용량도 모니터링할 수 있다.

시스템 메모리 사용량과 자바 프로세스 메모리 사용량

시스템 메모리 사용량은 시스템의 메모리 사용량을 의미하고, 자바 프로세스 메모리 사용량은 제니퍼 에이전트를 설치한 자바 애플리케이션이 사용하는 메모리 사용량을 의미한다. 단위는 MB이다.

시스템 메모리 사용량과 자바 프로세스 메모리 사용량은 제니퍼 에이전트가 수집하는 일반 성능 데이터로 실시간 30초 평균 값을 런타임 라인 차트를 통해서 확인할 수 있다.

또한 시스템 메모리 사용량과 자바 프로세스 메모리 사용량에 대한 5분 평균 값은 PERF_X_01~31 테이블의 SYS_MEM_USED 칼럼과 JVM_NAT_MEM 칼럼에 저장되고, 특정 날짜의 메모리 사용량 변화 추이는 라인 차트를 통해서 확인할 수 있다.

금일 시스템 메모리 사용량

시스템 CPU 사용률과 동일하게 시스템 메모리 사용량과 자바 프로세스 메모리 사용량을 수집하려면 Native 모듈이 올바르게 설치되어 있어야 한다.

CLR 힙 메모리 사용량

CLR 힙 메모리 사용량은 다음의 코드로 얻어진 값을 의미한다.

_jvmmem.used = GC.GetTotalMemory(false);

앞의 코드를 통해서 수집한 값의 단위는 바이트이지만, 제니퍼는 이를 MB로 전환해서 사용한다.

힙 메모리 사용량은 제니퍼 에이전트가 수집하는 일반 성능 데이터로 실시간 30초 평균값을 런타임 라인 차트를 통해서 확인할 수 있다. 또한 힙 메모리 사용량에 대한 5분 평균값은 PERF_X_01~31 테이블의 HEAP_TOTAL 칼럼과 HEAP_USED 칼럼에 저장되고, 특정 날짜의 힙 메모리 사용량 변화 추이는 라인 차트를 통해서 확인할 수 있다.

힙 메모리 사용률은 시스템의 물리 메모리 전체에 대한 힙 메모리 사용량의 비율을 의미한다. 단위는 퍼센트이다.

힙 메모리 사용량, 힙 메모리 사용률 등을 나타내는 런타임 라인 차트에서는 특정 제니퍼 에이전트에 대한 가비지 콜렉션을 수행할 수 있다.

CLR 힙 메모리 사용량

DB 연결 모니터링

데이터베이스 연동은 엔터프라이즈 애플리케이션 성능에 많은 영향을 미친다. 따라서 제니퍼는 이에 대한 성능 분석 및 조치를 위한 DB 모니터링을 제공한다. DB 모니터링으로 수집하는 데이터는 다음과 같다.

DB 모니터링을 위한 기본 설정

DB 사용을 모니터링을 하려면 제니퍼 에이전트의 enable_db_sql_trace 옵션을 true로 설정해야 한다. 기본 값은 true이다. 이 옵션을 false로 설정하면 DB 모니터링이 이루어지지 않는다.

enable_db_sql_trace = true

DB 커넥션 개수 모니터링

추적 가능한 DB 커넥션 상태는 다음과 같다.

DB 커넥션 유형

유형

설명

대기 중인 DB 커넥션 개수(IDLE)

DB 커넥션 풀에서 대기 중인 DB 커넥션 개수

할당된 DB 커넥션 개수(ALLOCATED)

서비스 쓰레드가 DB 커넥션 풀로부터 할당받은 DB 커넥션 개수

사용 중인 DB 커넥션 개수(ACTIVE)

(닷넷 버전에서는 지원하지 않음)

DB 커넥션 개수는 제니퍼 에이전트가 수집하는 일반 성능 데이터로 해당 시점의 값을 이퀄라이저 차트와 런타임 라인 차트를 통해서 확인할 수 있다.

실시간 JDBC 커넥션 개수

또한 DB 커넥션 개수에 대한 5분 평균 값은 PERF_X_01~31 테이블의 JDBC_IDLE, JDBC_ALLOC, JDBC_ACTIVE 칼럼에 저장된다.

SQL 데이터 수집 방법

DB 모니터링은 다른 자원을 모니터링 하는 것에 비해 상당히 많은 데이터를 수집해야 한다. 애플리케이션이 수행하는 모든 SQL과 파라미터를 수집해야지만 문제가 있는 SQL에 대해서 튜닝 등의 작업을 할 수 있기 때문이다.

그래서 데이터 전송량을 줄이기 위해서 제니퍼 에이전트가 제니퍼 서버에 보내는 데이터에서는 SQL이 아닌 해당 SQL에 대한 해시 값을 사용한다. 그리고 별도의 방법을 통해서 해시 값에 대한 SQL을 수집해서 제니퍼 서버의 SQLS 테이블에 저장한다.

그리고 SQLS 테이블에 저장되는 SQL의 개수를 줄이기 위해서, SQL에 있는 상수를 파라미터로 처리하여 저장한다. 예를 들어, 자바 애플리케이션이 처리한 다음 SQL은 별도의 SQL이다.

SELECT * FROM TABLE WHERE ID = ? AND AGE = 32 AND NAME = ‘KIM’
SELECT * FROM TABLE WHERE ID = ? AND AGE = 27 AND NAME = ‘LEE’

그러나 앞의 코드는 상수를 제외한 기본적인 구조는 동일하다. 이를 그대로 SQLS 테이블에 저장하면 데이터의 양이 많아진다. 예를 들어, 다음 코드가 수행된다면 10,000개의 SQL이 SQLS 테이블에 저장되어야 한다.

IDbCommand command = ...;
IDataReader dr = null;
for (int i = 0; i < 10000; i++)
{
   command.CommandText = "SELECT * FROM USERS WHERE ID = " + I;
   dr = command.ExceuteReader();
   ...
}

이를 해결하기 위해서 상수 중에서 문자는 [$]로, 숫자는 [#]으로 변경하여 SQLS 테이블에 저장한다.

따라서 SQLS 테이블에는 다음 SQL 만이 저장된다.

SELECT * FROM TABLE WHERE ID = ? AND AGE = # AND NAME = ‘$’

그리고 X-View 프로파일 데이터 등에서는 상수 파라미터는 파라미터 1로 나타나고, 바인딩 파라미터는 파라미터 2로 표시된다. 바인딩 파라미터는 java.sql.PreparedStatement 객체로 수행하는 SQL에서 [?]로 표시되는 파라미터를 의미한다.

SQL 예외 로그 기록

애플리케이션에서 SqlException이 발생하면, 관련 내용을 제니퍼 에이전트 로그 파일에 기록할 수 있다. 이 내용을 기록하려면 제니퍼 에이전트의 enable_sql_error_trace 옵션을 true로 설정한다. 기본 값은 false 이다.

enable_sql_error_trace = true

단, 정상적인 상황에서도 비즈니스 로직에 종속적으로 SqlException이 발생할 수 있다. 따라서 SqlException을 오류 혹은 장애로 단정지을 수는 없다. 또한 반복적인 SqlException의 발생으로 로그를 빈번하게 기록하면 성능 저하가 발생할 수 있으므로, 필요 시에만 이 옵션을 true로 지정하고 평상시에는 false로 지정하는 것을 권장한다.

DB 모니터링과 예외 발생

DB 모니터링과 관련해서 발생하는 예외는 다음과 같다.

SQL 응답 속도의 지연

SQL 응답 속도가 임계치를 초과하면 WARNING_DB_BAD_RESPONSE 예외가 발생한다. 임계치는 제니퍼 에이전트의 sql_bad_responsetime 옵션으로 설정한다. 기본 값은 20000이고 단위는 밀리 세컨드이다.

sql_bad_responsetime = 20000

Fetch 건수 초과

Fetch는 java.sql.ResultSet 객체의 next 메소드를 호출하는 것을 의미한다. 따라서 Fetch 건수는 next 메소드의 호출 건수를 의미한다. 트랜잭션이 수행되는 과정에서 동일한 java.sql.ResultSet 객체에 대한 Fetch 건수가 임계치를 초과하면 WARNING_JDBC_TOOMANY_RS_NEXT 예외가 발생한다. 임계치는 제니퍼 에이전트의 jdbc_resultset_warning_fetch_count 옵션으로 설정한다. 기본 값은 10000 이다.

db_reader_warning_fetch_count = 10000

DB 리소스 미반환 추적

SqlConnection 객체 등을 DB 자원이라고 한다. 이 객체들을 사용한 후에 해당 객체의 Close (또는 Dispose) 메서드를 호출하지 않으면 DB 자원 미반환 예외가 발생한다.

그런데 문제가 되는 것은 DB 자원 미반환을 감지하는 시점이다. 웹 응용 프로그램의 경우 ProcessRequest 처리 완료 후에 해당 요청에서 사용된 DB 자원에 대한 미반환을 체크하고 일반적인 응용 프로그램의 경우에는 메서드 단위의 실행마다 미반환을 체크한다.

DB 미반환과 관련한 예외는 다음과 같다.

WARNING_DB_CONN_UNCLOSED

애플리케이션에서 IDbConnection 객체를 사용한 후에 Close (또는 Dispose) 메서드를 호출하지 않으면 WARNING_DB_CONN_UNCLOSED 경고가 발생한다.