Spring
[Spring] HikariCP 동작 방식
누구세연
2024. 9. 29. 22:56
HikariCP의 성능과 효율성을 구체적으로 이해하고 이를 실제로 어떻게 구현했는지 파악해 보겠습니다.👀
HikariCP의 아키텍처
HikariCP는 간단한 설정을 통해 고성능 커넥션 풀링을 지원합니다. 내부적으로는 커넥션을 풀에 저장해 놓고 필요할 때마다 커넥션을 효율적으로 관리합니다. 그 과정을 관리하는 주요 클래스들은 다음과 같습니다.
- HikariDataSource
HikariCP의 시작점으로 기본 설정을 통해 커넥션 풀을 초기화하고 관리합니다. - HikariPool
실제 커넥션 풀을 관리하며 커넥션을 빌려주고 반환하는 과정을 처리합니다. - PoolEntry
풀내의 각각 커넥션을 표현하는 클래스입니다. - ProxyConnection
데이터베이스와의 실제 커넥션을 감싸서 풀에 반환할 때 사용하는 래퍼 클래스입니다.
HikariDataSource의 동작 방식
HikariDataSource는 커넥션 풀을 초기화하는 중심적인 클래스입니다. 이 클래스의 역할과 어떻게 HikariPool과 연결되는지 설명할 수 있습니다.
public class HikariDataSource extends HikariConfig implements DataSource {
private final HikariPool pool;
public HikariDataSource(HikariConfig configuration) {
super(configuration);
this.pool = new HikariPool(this);
}
@Override
public Connection getConnection() throws SQLException {
return pool.getConnection();
}
}
- `HikariDataSource`는 HikariConfig를 상속받아 사용자 설정을 관리하고 HikariPool을 생성하여 커넥션 풀을 제어합니다.
- `getConnection()`메서드를 호출하면 HikariPool에서 사용 가능한 커넥션을 반환합니다.
HikariPool의 동작
`HikariPool`클래스는 HikariCP의 핵심 클래스 중 하나로 실제 커넥션 풀을 관리하고 커넥션 할당 및 반환을 처리합니다.
내부적으로 LinkedBlockingQueue를 사용하여 풀을 구성하며 요청이 들어오면 즉시 사용한 커넥션을 제공하는 방식입니다.
public final class HikariPool {
private final LinkedBlockingQueue<PoolEntry> connectionBag;
public HikariPool(HikariConfig config) {
this.connectionBag = new LinkedBlockingQueue<>(config.getMaximumPoolSize());
initializeConnections(config);
}
public Connection getConnection() throws SQLException {
PoolEntry entry = connectionBag.poll();
return entry != null ? entry.createProxyConnection() : null;
}
}
- `connectionBag`: 커넥션을 저장하는 큐로 사용 가능한 커넥션을 관리합니다.
- `initializeConnections`: 풀을 초기화하면서 미리 설정된 개수만큼 커넥션을 생성하여 풀에 저장합니다.
- `getConnection`: 요청이 들어오면 풀에서 사용 가능한 커넥션을 가져오고 없을 경우 null을 반환하거나 대기하게 할 수 있습니다.
ProxyConnection의 역할
HikariCP는 풀에서 빌려간 커넥션을 다시 풀로 반환할 수 있도록 Proxy 패턴을 활용합니다.
ProxyConnection 클래스는 진짜 데이터베이스 커넥션을 감싸는 역할을 합니다.
public class ProxyConnection implements Connection {
private final Connection delegate;
private final HikariPool pool;
public ProxyConnection(Connection delegate, HikariPool pool) {
this.delegate = delegate;
this.pool = pool;
}
@Override
public void close() throws SQLException {
pool.releaseConnection(this);
}
}
- `ProxyConnection`은 실제로 데이터베이스에 연결된 커넥션을 감싸고 있습니다. 사용자는 이 커넥션을 통해 쿼리를 실행하고 커넥션을 반환할 때 `close()`메서드를 호출합니다.
- `close()`메서드는 진짜로 커넥션을 닫는 대신 풀로 다시 반환합니다.
Connection Timeout과 Pool Size 설정의 처리
HikariCP가 빠른 커넥션 풀로 알려진 중요한 이유 중 하나는 Connection Timeout과 Maximum Pool Size를 정교하게 처리하기 때문입니다.
config.setConnectionTimeout(30000); // 30초 대기
config.setMaximumPoolSize(10); // 최대 10개의 커넥션
- Connection Timeout
HikariCP는 커넥션을 기다리는 시간을 제어할 수 있는 타임아웃을 제공합니다.
설정한 시간 내에 커넥션을 얻지 못하면 예외가 발생합니다. - Pool Size
Maximum Pool Size는 풀 내에 동시에 유지할 수 있는 커넥션의 최대 수를 정의합니다.
HikariCP는 이 수치를 유지하며 필요시 풀을 확장 또는 축소할 수 있습니다.
HikariCP의 성능 최적화
HikariCP의 주요 성능 최적화 포인트는 다음과 같습니다.
- Fast Fail
커넥션을 특히 사용할 수 없다면 빠르게 실패하고 긴 대기 시간을 방지합니다. - Efficient Connection Handling
커넥션을 반환할 때 풀로 다시 반환하고 바로 사용할 수 있도록 설계되어 대기 시간을 줄입니다. - Lightweight Objects
HikariCP는 불필요한 객체 생성을 줄여 메모리 사용량을 최소화하고 가비지 컬렉션의 부담을 덜어줍니다.
💡 내부적으로 효율적인 커넥션 관리와 최적화된 성능을 위해 다양한 기술들이 사용되고 있으며, 이 구조 덕분에 HikariCP가 높은 성능을 자랑하는 커넥션 풀로 자리 잡고 있습니다.