티스토리 뷰
HikariPool 생성자
super(config);
this.connectionBag = new ConcurrentBag<>(this);
this.suspendResumeLock = config.isAllowPoolSuspension() ? new SuspendResumeLock() : SuspendResumeLock.FAUX_LOCK;
this.houseKeepingExecutorService = initializeHouseKeepingExecutorService();
super(this)
HikariPool은 PoolBase를 상속받아 구현한 클래스로서 기본 값을 설정합니다.
PoolBase(final HikariConfig config)
{
this.config = config;
this.networkTimeout = UNINITIALIZED;
this.catalog = config.getCatalog();
this.schema = config.getSchema();
this.isReadOnly = config.isReadOnly();
this.isAutoCommit = config.isAutoCommit();
this.exceptionOverride = UtilityElf.createInstance(config.getExceptionOverrideClassName(), SQLExceptionOverride.class);
this.transactionIsolation = UtilityElf.getTransactionIsolation(config.getTransactionIsolation());
this.isQueryTimeoutSupported = UNINITIALIZED;
this.isNetworkTimeoutSupported = UNINITIALIZED;
this.isUseJdbc4Validation = config.getConnectionTestQuery() == null;
this.isIsolateInternalQueries = config.isIsolateInternalQueries();
this.poolName = config.getPoolName();
this.connectionTimeout = config.getConnectionTimeout();
this.validationTimeout = config.getValidationTimeout();
this.lastConnectionFailure = new AtomicReference<>();
initializeDataSource();
}
suspendResumeLock
config.isAllowPoolSuspension()의 값은 따로 설정하지 않았다면 디폴트 값인 false입니다.
따로 설정 값을 주지 않는다면 SuspendResumeLock.FAUX_LOCK이 선택되며 별다른 구현체가 없이 껍데기만 존재하게 됩니다.
public static final SuspendResumeLock FAUX_LOCK = new SuspendResumeLock(false) {
@Override
public void acquire() {}
@Override
public void release() {}
@Override
public void suspend() {}
@Override
public void resume() {}
};
allowPoolSuspension 설정값을 true로 하지 않는다면 아무런 동작을 하지 않는 것과 동일하다.
houseKeepingExecutorService
this.houseKeepingExecutorService = initializeHouseKeepingExecutorService();
private ScheduledExecutorService initializeHouseKeepingExecutorService()
{
if (config.getScheduledExecutor() == null) {
final ThreadFactory threadFactory = Optional.ofNullable(config.getThreadFactory()).orElseGet(() -> new DefaultThreadFactory(poolName + " housekeeper", true));
final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1, threadFactory, new ThreadPoolExecutor.DiscardPolicy());
executor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
executor.setRemoveOnCancelPolicy(true);
return executor;
}
else {
return config.getScheduledExecutor();
}
}
public static final class DefaultThreadFactory implements ThreadFactory {
private final String threadName;
private final boolean daemon;
public DefaultThreadFactory(String threadName, boolean daemon) {
this.threadName = threadName;
this.daemon = daemon;
}
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r, threadName);
thread.setDaemon(daemon);
return thread;
}
}
daemon
데몬 스레드는 주 스레드의 작업을 돕는 보조적 역할을 담당하는 쓰레드로서 주 스레드가 종료했을 때 데몬 스레드도 같이 종료한다.
ScheduledThreadPoolExecutor
어떤 작업을 일정 시간 지연 후에 수행하거나, 일정 시간 간격으로 주기적으로 실행해야할 때 사용
HikariCP에서는 scheduleWithFixedDelay 메소드를 사용하며, 작업이 완료되면 일정 시간 뒤에 다시 실행시키는 작업을 진행합니다.
checkFailFast();
if (config.getMetricsTrackerFactory() != null) {
setMetricsTrackerFactory(config.getMetricsTrackerFactory());
}
else {
setMetricRegistry(config.getMetricRegistry());
}
setHealthCheckRegistry(config.getHealthCheckRegistry());
handleMBeans(this, true);
ThreadFactory threadFactory = config.getThreadFactory();
checkFailFast
설정값 확인
final long initializationTimeout = config.getInitializationFailTimeout();
if (initializationTimeout < 0) {
return;
}
createPoolEntry
해당 메서드에서 maxLifetime 과 keepaliveTime 값에 따라 ScheduledThreadPoolExecutor의 값들을 poolEntry에 쌓는 작업을 진행합니다.
final long startTime = currentTime();
do {
final PoolEntry poolEntry = createPoolEntry();
if (poolEntry != null) {
if (config.getMinimumIdle() > 0) {
connectionBag.add(poolEntry);
logger.debug("{} - Added connection {}", poolName, poolEntry.connection);
}
else {
quietlyCloseConnection(poolEntry.close(), "(initialization check complete and minimumIdle is zero)");
}
return;
}
if (getLastConnectionFailure() instanceof ConnectionSetupException) {
throwPoolInitializationException(getLastConnectionFailure().getCause());
}
quietlySleep(SECONDS.toMillis(1));
} while (elapsedMillis(startTime) < initializationTimeout);
connectionBag.add를 통해 해당 poolEntry를 넣는 작업을 진행합니다. 초기시간이 될 때까지..
개인적인 생각으로 메소드명은 validation만 할 것 같았는데 poolEntry를 connectionBag에 넣는 작업을 할 줄은 몰랐다..
생성자 중간 부분
handleMBeans(this, true);
ThreadFactory threadFactory = config.getThreadFactory();
final int maxPoolSize = config.getMaximumPoolSize();
LinkedBlockingQueue<Runnable> addConnectionQueue = new LinkedBlockingQueue<>(maxPoolSize);
this.addConnectionQueueReadOnlyView = unmodifiableCollection(addConnectionQueue);
this.addConnectionExecutor = createThreadPoolExecutor(addConnectionQueue, poolName + " connection adder", threadFactory, new ThreadPoolExecutor.DiscardOldestPolicy());
this.closeConnectionExecutor = createThreadPoolExecutor(maxPoolSize, poolName + " connection closer", threadFactory, new ThreadPoolExecutor.CallerRunsPolicy());
this.leakTaskFactory = new ProxyLeakTaskFactory(config.getLeakDetectionThreshold(), houseKeepingExecutorService);
this.houseKeeperTask = houseKeepingExecutorService.scheduleWithFixedDelay(new HouseKeeper(), 100L, housekeepingPeriodMs, MILLISECONDS);
handleMBeans(this, true)
MBean을 등록하는 메서드
JMX
Java Management Extension
MBean: Manged Bean => 플랫폼 혹은 사용자에 의해 만들어진 모니터링용 객체
Instrumentation 계층 - 관리 Bean(MBean)이라고 하는 특수 Java Bean 내에서 자원을 랩핑할 수 있는 방법을 지시합니다.
agent 계층 - 관리 인프라 구조를 제공하는 에이전트 및 MBean 서버로 구성됩니다. 구현된 서비스는 다음과 같습니다.
- 모니터링
- 이벤트 알림
- 타이머
management 계층 - 외부 관리 애플리케이션이 프로토콜, API 등의 관점에서 기본적인 계층과 상호작용할 수 있는 방법을 정의합니다. 이 계층은 J2EE(Java 2 Platform, Enterprise Edition) 스펙의 일부인 분산 서비스 스펙(JSR-077)의 구현을 사용합니다.
ThreadFactory
내용참고: ThreadFactory
- 스레드에 대해서 의미있는 이름을 부여할 수 있다. 즉 어떤 목적을 가지고 작업을 하는 것에 대해서 파악하기 쉽다.
- 스레드 수 및 기타 세부 정보와 같이 생성된 스레드에 대한 통계를 얻을 수 있습니다. 통계를 기반으로 새 스레드 생성을 제한할 수 있습니다.
- 스레드의 데몬 상태를 설정할 수 있습니다.
- 스레드 우선 순위를 설정할 수 있습니다.
- 모든 기능을 하나의 클래스로 제한할 수 있습니다.
LinkedBlockingQueue
일반 큐와 다른 점이 있다면 다음과 같다.
private final ReentrantLock takeLock = new ReentrantLock();
private final Condition notEmpty = takeLock.newCondition();
private final ReentrantLock putLock = new ReentrantLock();
private final Condition notFull = putLock.newCondition();
ReentrantLock 은 기본적으로 synchronized와 같이 동기화 목적으로 사용되는 lock으로서 동일한 성격을 가지고 있다.
차이점이 있다면 특정 자원에 대해서 관리할 수 있다는 점이다.
나머지 부분은 중간에 한 번 설명한 적이 있는 것 같아 넘어가도록 하겠습니다.
다음번에 HikariCP getConnection()에 대해서 알아보도록 하겠습니다. 그럼 20000
'JVM > Spring' 카테고리의 다른 글
[Spring] Scope (Prototype & Singleton) (2) | 2022.09.13 |
---|---|
[Hikari CP] 光 살펴보기 - 4 (0) | 2022.04.29 |
[Hikari CP] 光 살펴보기 - 2 (0) | 2022.04.27 |
[Hikari CP] 光 살펴보기 - 1 (0) | 2022.04.26 |
[Spring] AOP (0) | 2022.04.05 |
- Total
- Today
- Yesterday
- 파이썬
- 2021 KAKAO BLIND RECRUITMENT
- 알고리즘
- DRF
- django
- Pattern
- env
- Collections
- setattr
- Python
- thread
- postgres
- Java
- Command Line
- ubuntu
- BFS
- 그래프
- 백준
- 프로그래머스
- docker
- PostgreSQL
- Spring
- Linux
- 카카오
- 자바
- dockerignore
- headers
- 면접
- docker-compose
- Celery
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |