Connection Pool 이해하고 사용하기
connection pool 이란?
client 에서 요청이 올때마다 매번 connection 을 맺게 되면 TCP/IP 의 3way handshake 가 발생하게 되고
그만큼 client 에게 응답이 늦어지므로 사용자의 편의성이 하락 할 수 있다.
그리고 Database 의 connection 이 무한하게 증가 함으로 그다지 좋은 방법은 아니라 실무에서는 필수적으로 Connection Pool 을 사용하여 Database 를 사용한다.
Spring boot 2.0 의 Connection Pool
spring boot 2.0 에서는 connection pool 의 기본을 hikaricp 를 사용하도록 되어 있다.
hikaricp 가 궁금하시다면 밑에 링크를 참조하자
DriverManger Connection
기존에 Java 에서 Database 와 Connection 을 맺으려면 DriverManger 를 통해서 connection 해야 했다.
@Test
void driverManger() throws SQLException {
Connection connection1 = DriverManager.getConnection(URL, USERNAME, PASSWORD);
Connection connection2 = DriverManager.getConnection(URL, USERNAME, PASSWORD);
log.info("connection = {}, class = {}", connection1, connection1.getClass());
log.info("connection = {}, class = {}", connection2, connection2.getClass());
}
하지만 DriverManger 를 사용하여 connection 을 하게되면 위에서 말했던 문제점 들이 발생하고
유지보수 측면에서도 설정과 사용이 분리 되지 않아 썩 좋은 코드는 아니다.
설정과 사용의 분리
@Test
void dataSourceDriverManger() throws SQLException {
// DriverMangerDataSource - 항상 새로운 커넥션을 획득
DataSource dataSource = new DriverManagerDataSource(URL, USERNAME, PASSWORD);
useDateSource(dataSource);
}
private void useDateSource(DataSource dataSource) throws SQLException {
Connection connection1 = dataSource.getConnection();
Connection connection2 = dataSource.getConnection();
log.info("connection = {}, class = {}", connection1, connection1.getClass());
log.info("connection = {}, class = {}", connection2, connection2.getClass());
}
DriverMangerDataSource 를 사용하여 설정을 하고 따로 method 를 만들어 사용을 분리하였다.
DriverMangerDataSource 는 내부적으로 DataSource 를 구현하고 있는 구현체 이다.
하지만 위와 같은 코드도 client 에서 여러 요청이 왔을때 매번 connection 을 맺기 때문에 위와 같은 문제를 해결 하지 못했다.
Connection Pool 만들어 사용하기
@Test
void dataSourceConnectionPool() throws SQLException, InterruptedException {
// connection pooling
HikariDataSource hikariDataSource = new HikariDataSource();
hikariDataSource.setJdbcUrl(URL);
hikariDataSource.setUsername(USERNAME);
hikariDataSource.setPassword(PASSWORD);
hikariDataSource.setMaximumPoolSize(10); // Default 10
hikariDataSource.setPoolName("MyPool");
useDateSource(hikariDataSource);
/**
* pool 을 추가하는 과정은 application 에 영향을 주지 않도록 하기 위해서
* 별도의 thread 를 사용하여 추가한다.
* 이 과정에 있어서 sleep 1000 을 주석 처리 하게 되면 10개의 pool 이 다 생성되기도 전에 test code 가 끝날 가능성이 있다.
*/
Thread.sleep(1000);
}
private void useDateSource(DataSource dataSource) throws SQLException {
Connection connection1 = dataSource.getConnection();
Connection connection2 = dataSource.getConnection();
log.info("connection = {}, class = {}", connection1, connection1.getClass());
log.info("connection = {}, class = {}", connection2, connection2.getClass());
}
Datasource 를 구현한 HikariDataSource 를 사용하여 Pool 을 10 개를 생성하고 connection 을 맺을때 미리 생성해둔 pool 에서 connection 을 가져와 데이터베이스와 연결을 맺고 사용이 끝나면 반납하는 형식으로 코드를 작성하였다.
하지만 요기서 몇가지 주의해야 할 점이 있는데 pool 을 생성하고 추가하는 과정은 비용이 저렴하지 않으므로
application 을 실행에 영향을 주지 않도록 하기 위해 별도의 thread를 사용하여 생성 및 추가한다.
이 과정에 있어서 Tread.sleep(1000) 이란 코드가 없다면 10개를 생성 및 추가 하기전에 test code 가 끝나는걸 볼 수 있다.
그리고 2번째 주의사항은 connection 이 10개 가 넘어버린다면 ? 어떻게 될까
정답은 hikaricp 에서 기본적으로 30초 이상 응답이 지연시 강제로 connection 을 끊어버린다.
실무에서 는 좀더 짧은 시간을 가지는게 사용자 편의를 위해 좋을 것 같다.
'Java > java - spring' 카테고리의 다른 글
낙관적 LOCK 과 비관적 LOCK - (JPA, Mysql) (0) | 2022.07.06 |
---|---|
JPA - Proxy (0) | 2022.07.02 |
상속 관계 매핑 Entity 를 QueryDsl 에서 사용하기 (0) | 2022.05.23 |
Failed to start bean 'documentationPluginsBootstrapper' 오류 해결 (0) | 2022.03.02 |
JPA 성능 최적화 - N + 1 문제 해결 하기 (0) | 2022.01.30 |
댓글
이 글 공유하기
다른 글
-
낙관적 LOCK 과 비관적 LOCK - (JPA, Mysql)
낙관적 LOCK 과 비관적 LOCK - (JPA, Mysql)
2022.07.06 -
JPA - Proxy
JPA - Proxy
2022.07.02 -
상속 관계 매핑 Entity 를 QueryDsl 에서 사용하기
상속 관계 매핑 Entity 를 QueryDsl 에서 사용하기
2022.05.23 -
Failed to start bean 'documentationPluginsBootstrapper' 오류 해결
Failed to start bean 'documentationPluginsBootstrapper' 오류 해결
2022.03.02