본문 바로가기

개발/Linux & DevOps

DBCP 설정, maxIdle minIdle maxActive 얼마정도가 적합할까?

디비 커넥션 "풀"

DBCP. 디비 커넥션 풀. 이 포스트에 향긋한 풀냄새를 퍼트려본다.

 

회사에서 최근 페이코인 이슈로 인해 통신량이 폭주해 서버증설 및 튜닝을 진행했다.

이때 필히 알아야하는 트래픽 최적화 요소중 DBCP 에 대해서 공부해보자.


DBCP 가 뭐고, 왜 필요한데?

클라이언트에서 웹, 웹서버, 디비 까지 한번 왔다갔다할 때

가장 시간이 많이 소요되는 곳은 웹서버에서 DB서버에 최초로 연결되어

Connection 객체를 생성하는 부분이다.

 

이 시간을 단축시킬 수 있는 것이 DBCP 이다. DB Connection Pool, 즉 미리 DB서버와의 연결을 생성해놓고, DB서버와 통신이 필요할 때 Connection 객체를 빌려쓰는 것이다.

 

이 때 최초 몇개의 Connection 객체를 생성할 것인가,

최소 몇개를 유지할 것인가,

최대 몇개를 유지할 것인가,

최대 동시 통신하는 Connection 은 몇개 까지 허용할 것인가

등등 을 properties 파일을 통해 설정하게 된다.

 

자세히 몇몇 요소들을 살펴보자.

  • session.url = 어떤 디비에 연결되어있는가 (123.123.123.123 : 3306/db_name?blah-blah=false)
  • session.maxActive = 동시 사용되는 최대 Connection 객체 수
  • session.maxIdle = Connection 객체 사용 후 반환할 때, 최대 유지되는 객체 수
  • session.minIdle = 최소한 유지되야하는 Connection 객체 수
  • initalSize 현재 설정되어있지 않다 (default = 0) 하지만 많이 언급되고 사용되는 설정변수이다.
  • maxWait 현재 설정되어있지 않다 (default = 무한대) 하지만 많이 언급되고 사용되는 설정변수이다.
  • testOnBorrow = Connection 을 얻어왔을 때 validationQuery를 던져 확인해볼까말까 설정
  • validationQuery = select 1 보통 이걸로 한다.

이정도가 설정되어있다.

 

설정할 때 논리적 오류가 없으려면 :

  • maxActive >= inistalSize - 최초 생성 수가 최대 동시사용 개수보다 많으면 논리적으로 말이 안된다.
  • maxIdle > minIdle - 최대 유지되야하는 Connection 객체수는 최소보다 작을 수 없다.
  • maxIdle = maxActive 권장 - 만약 maxIdle = 5, maxActive = 10 이라면, 5개의 커넥션이 모두 사용중일 때 커넥션이 한개 더 생긴다면, maxActive는 아직 여유가 있으니 프로세스는 계속 진행되고, 그러면 새로 연결을 하고, 반환해도 이미 꽉차 있으니 그 커넥션은 닫히게 된다. 5개의 커넥션이 계속 사용중이라면 계속 새로 연결, 다시 닫기가 반복되니 DBCP를 사용하는 의미가 아예 없어진다.  maxIdle 과 maxActive 는 같은 값이거나 큰 차이가 없어야 바람직하다.

 

현재 자사 서버는 maxIdle, minIdle = 3, maxActive = 10 으로 설정되어 있는데,

이는 서버컴퓨터 성능에 비해 많이 낮은 설정이다.

숫자를 더 높여서 성능을 향상시킬 수 있다.

얼마 정도 높여야 적당한지는 스트레스 테스트 혹은 로그 분석을 통해 산출해낼 수 있다.


얼마정도가 적당할지 Araboja

그래서 어떤 값으로 해야 적당할까?

이는 컴퓨터 성능에 따라 달라지기 때문에 테스트를 진행해보는 것이 가장 정확하다.

테스트 방법은 스트레스 테스트 / 로그 분석이 있다.

 

스트레스 테스트는 말 그대로 얼만큼의 부하(負荷)를 견딜 수 있는지 테스트 해보는 것이다. 서버가 다운될 때까지 극한으로 괴롭히는 것이다. 의미에서 유추할 수 있듯 실 서버에는 절대 할 수 없다.

 

(스트레스 테스트를 한번 진행해본 후기가 궁금하다면 여기로)

 

나와 같은 경우 실 서버에 대한 조사를 원하기 때문에 로그를 분석해야 한다. 아쉽게도 기본 아파치 톰캣에서 동시 Active Connection 개수를 로깅해주지 않는다. Scouter 를 사용하고 있지만 Scouter 에서도 tomcat DBCP 에 대한 로깅만 지원할 뿐, common DBCP에 대한 지원은 추후에도 업데이트 계획이 없다고 한다. 

Note:
common DBCP, tomcat DBCP 는 엄연히 다르다. 역할은 같지만, tomcat DBCP 를 사용하려면 그에 따른 세팅이 필요하다.
tomcat DBCP 가 멀티스레드를 지원, 높은 성능, 쉬운 디버깅 등 여러 장점을 어필하고 있지만...
대부분 common DBCP 를 사용한다.

 

그래서 찾아본 결과 Btrace를 통한 로깅을 많이 추천한다. 

Btrace는 이미 실행되고 있는 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);
  }
}

보면 알겠지만 전부 print 이다. 읽기 편하려고 쓴 코드가 태반이다.

이 DbcpMonitorSimple.java 속에 dbcp 정보를 입력하고,

Btrace [pid] DbcpMonitorSimple.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

==========

 

실서버는 내 마음대로 할 수 없기 때문에 이 글을 통해 관리자 분들께 의견을 전달하고,

동의를 얻게 된다면 시도해볼 수 있다면 좋겠다.

 

 

 

 

출처:

blog.benelog.net/2855201.html (Btrace로 DBCP 모니터링)

www.holaxprogramming.com/2013/01/10/devops-how-to-manage-dbcp/ (DB Connection Pool에 대한 이야기)

 

 

 

♡도움이 되셨다면 공감 및 광고클릭으로 응원해주세욥 :D

반응형