Btrace로 DBCP의 connection정보를 모니터링 하기 by 정상혁

 Connection pool을 library로 DBCP를 많이 사용하고 있습니다. DataSouce가 선언되어 있는 설정 파일을 보면 min, max Connection 숫자는 쉽게 알 있지만, 현재 Active 한 것이 몇개 인지등은 실행시간에 쉽게 알아보기가 쉽지가 않죠. 그래서 JMX로 현재 Active한 Connection 수 등을 노출하는, DBCP를 한번 감싼 DataSource를 사용하기도 합니다.


 Btrace를 이용하면 비교적 간단하게 DBCP의 속성들을 값들을 확인할 수 있습니다. 이미 실행되고 있는 JVM에도 붙일 수 있으니 설정을 바꾸고 WAS를 재시작하지 않아도 됩니다.


 아래와 같이 간단한 소스로도 가능합니다.


 

import static com.sun.btrace.BTraceUtils.*;


import java.lang.reflect.Field;


import com.sun.btrace.BTraceUtils.Sys;

import com.sun.btrace.annotations.BTrace;

import com.sun.btrace.annotations.OnMethod;

import com.sun.btrace.annotations.Self;


 

@BTrace

public class DbcpMonitorSimple {

  private static final String DS_CLASS = "org.apache.commons.dbcp.BasicDataSource";


  @OnMethod(clazz = DS_CLASS, method = "getConnection")

  public static void onGetConnection(@Self Object basicDataSource) {

 

    Field urlField = field(DS_CLASS, "url");

    Object url = get(urlField, basicDataSource);

    print("=====DBCP BasicDataSource info (");

    print(url);

    println(" ) ==========");

    printFields(basicDataSource);

    Field poolField = field(DS_CLASS, "connectionPool");


    Object pool = get(poolField, basicDataSource);

    println("=====connectionPool (GenericObjectPool) info====");

    printFields(pool);

    println("==========");

    Sys.exit(0);

  }

}

 


DataSource.getConnection 요청이 있을 때 해당 객체를 얻어와서 속성값들을 찍어줍니다.


그리고 필요한 필드만 찍는다던지, 보기좋게 정렬한다던지 하는 작업은 필요에 따라 하면 되겠죠.


jps로 모니터링하고자 하는 JVM의 pid를 확인하고,

btrace [pid] DbcpSimpleMonitor.java로 실행하면 아래와 같이 속성값들을 쭉 찍어줍니다.


 

D:\workspace\btrace-dbcp\src\main\java>btrace 4288 DbcpMonitor.java

 

=====DBCP BasicDataSource info (jdbc:hsqldb:file:store;shutdown=true ) ========

{defaultAutoCommit=true, defaultReadOnly=null, defaultTransactionIsolation=-1, d

efaultCatalog=null, driverClassName=org.hsqldb.jdbcDriver, driverClassLoader=nul

l, maxActive=8, maxIdle=8, minIdle=0, initialSize=0, maxWait=-1, poolPreparedSta

tements=false, maxOpenPreparedStatements=-1, testOnBorrow=false, testOnReturn=fa

lse, timeBetweenEvictionRunsMillis=-1, numTestsPerEvictionRun=3, minEvictableIdl

eTimeMillis=1800000, testWhileIdle=false, password=, url=jdbc:hsqldb:file:store;

shutdown=true, username=sa, validationQuery=null, validationQueryTimeout=-1, con

nectionInitSqls=null, accessToUnderlyingConnectionAllowed=false, restartNeeded=t

rue, connectionPool=org.apache.commons.pool.impl.GenericObjectPool@1f31079, conn

ectionProperties={user=sa, password=}, dataSource=org.apache.commons.dbcp.Poolin

gDataSource@be8958, logWriter=java.io.PrintWriter@12b1ff9, abandonedConfig=null,

 closed=false, }

===== number of Active : 0

==========

 

 


 

 FIeld 객체를 얻어올 때 field(String,String)을 쓰면 static 필드초기화나 @OnMethod 메소드가 붙지 않은 메소드에서는 객체가 얻어지지 않는  에러가 있었습니다.

 인터넷을 찾아보니 아래와 같이 비슷한 현상을 겪은 사람이 있었습니다.

http://kenai.com/projects/btrace/forums/forum/topics/1366-Drilling-into-a-method-argument-s-properties


 결국  @OnMethod 가 붙지 않는 메소드에서 호출을 할 때는   field(classof(obj), "fieldName")과 같이 피해가는 방법을 썼습니다. 되도록 메소드에서 매번 호출할 필요가 없는 부분은 static 초기화를 시킬 수 있었으면 하는데, static 초기화로는 하는 것도 잘 되지 않았습니다. 직접 field(BasicDataSource.class, "fieldName)으로 를 참조하기는 것도 잘 안 되었고, field(String,String)으로는 참조가 안 되었습니다. 이것만 아니면 좀 더 최적된 호출을 할 수 있었을 것 같습니다.


첨부한 파일들은 아래와 같은 다소 다른 방식이나 출력형식으로 택했습니다.

1. DbcpMonitorSimple.java : BasicDataSource.getConnection이 한번 호출될 때 BasicDataSource의 모든 정보와 BasicDataSource.connetionPool의 정보를 출력

2. DbcpMonitor.java :  이벤트 방식은 1과 같고, BasicDataSource의 모든 필드와 BasicDataSource.connetionPool에서 _numActive 값만을 보여줌

3. DbcpActiveConnectionMonitor.java : 여러 개의 Datasource의 Active connection 갯수를 구할 때 사용. getConnection에서 URL별로 active connection 갯수를 저장해 두었다가, Btrace에서 이벤트를 날리면 출력을 해주고 종료

 

 첨부한 스크립트 중 1,2번은 getConnection이 한번 호출되고 나면 스크립트를 종료하는 구조라서 큰 부하는 없겠지만, 증가 추이 등의 통계 정보를 쌓는기능 등이 필요하다면 Field poolField = field(DS_CLASS, "connectionPool"); 같은 부분도 중복호출되지 않게 하는 처리가 필요합니다.

 

 소스는 gist에 올렸습니다. ( https://gist.github.com/1246239 )

 


덧글

  • 서승호 2011/09/28 18:57 # 삭제 답글

    우와~ 좋은 정보 감사합니다. 우선 Btrace에 익숙해져야겠네요.
댓글 입력 영역