-
[HikariCP] keepaliveTime 와 관련된 여러가지 실험Java 2024. 7. 22. 18:22반응형
- 목차
keepaliveTime 이란 ?
keepaliveTime 설정은 Idle Connection 과 관련이 있습니다.
HikariCP Connection Pool 에서 Idle Connection 은 idleTimeout 이후에 제거됩니다.
Idle Connection 이란 Connection 과 데이터베이스 사이에 맺어진 TCP Socket 사이에 어떠한 Packet 도 전달되지 않는 상태의 Socket 을 의미합니다.
즉, 어떠한 쿼리 요청도 발생하지 않는 Connection 을 Idle Connection 이라하며, 이는 10분이라는 기본값을 가집니다.
10분 동안 통신이 전무한 Connection 은 제거됩니다.
keepaliveTime 은 Idle Connection 으로 연결된 TCP Socket 으로 Ping 요청을 보내는 주기입니다.
이는 기본값으로 Disabled 되어 있습니다. (Default: 0 (disabled))
따라서 keepaliveTime 은 idleTimeout 보다 작게 설정하게 되면, Idle Connection 는 꾸준히 Connection 을 유지하게 됩니다.
KeepaliveTime 과 test query 살펴보기.
아래와 같이 HikariCP 의 ConnectionPool 를 설정합니다.
KeepaliveTime 을 1분으로 지정하고, 그 외 IdleTimeout 과 MaxLifetime 을 Keepalive Time 보다 큰 값을 설정합니다.
HikariConfig config = new HikariConfig(); config.setJdbcUrl("jdbc:mysql://mysql:3306/test?allowPublicKeyRetrieval=true&useSSL=false"); config.setUsername("root"); config.setPassword("1234"); config.setMinimumIdle(2); config.setMaximumPoolSize(5); config.setKeepaliveTime(60000); config.setIdleTimeout(70000); config.setConnectionTestQuery("select count(*) from test.member;"); config.setMaxLifetime(1200000);
그리고 Java Application 을 실행하게 되면 아래와 같이 "select count(*) from test.member" 라는 요청이 1분 간격으로 MySQL 서버로 전송됨을 확인할 수 있습니다.
저는 ConnectionTestQuery 로 "select count(*) from test.member" 를 지정하였기 때문에 이러한 쿼리가 1분 간격으로 요청됩니다.
01:21:18.619680 IP fbbbd46ffc0b.57832 > mysql.mysql.mysql: Flags [P.], seq 1327:1367, ack 1399, win 524, options [nop,nop,TS val 2718954740 ecr 159002098], length 40 0x0000: 4500 005c 8348 4000 4006 5f2a ac12 0003 E..\.H@.@._*.... 0x0010: ac12 0002 e1e8 0cea 33f6 b53c 64da a2b8 ........3..<d... 0x0020: 8018 020c 5878 0000 0101 080a a20f f4f4 ....Xx.......... 0x0030: 097a 2df2 2400 0000 0300 0173 656c 6563 .z-.$......selec 0x0040: 7420 636f 756e 7428 2a29 2066 726f 6d20 t.count(*).from. 0x0050: 7465 7374 2e6d 656d 6265 723b test.member; 01:22:18.561244 IP fbbbd46ffc0b.57832 > mysql.mysql.mysql: Flags [P.], seq 1367:1407, ack 1456, win 524, options [nop,nop,TS val 2719014681 ecr 159062042], length 40 0x0000: 4500 005c 834a 4000 4006 5f28 ac12 0003 E..\.J@.@._(.... 0x0010: ac12 0002 e1e8 0cea 33f6 b564 64da a2f1 ........3..dd... 0x0020: 8018 020c 5878 0000 0101 080a a210 df19 ....Xx.......... 0x0030: 097b 181a 2400 0000 0300 0173 656c 6563 .{..$......selec 0x0040: 7420 636f 756e 7428 2a29 2066 726f 6d20 t.count(*).from. 0x0050: 7465 7374 2e6d 656d 6265 723b test.member; 01:23:18.504583 IP fbbbd46ffc0b.57832 > mysql.mysql.mysql: Flags [P.], seq 1407:1447, ack 1513, win 524, options [nop,nop,TS val 2719074624 ecr 159121980], length 40 0x0000: 4500 005c 834c 4000 4006 5f26 ac12 0003 E..\.L@.@._&.... 0x0010: ac12 0002 e1e8 0cea 33f6 b58c 64da a32a ........3...d..* 0x0020: 8018 020c 5878 0000 0101 080a a211 c940 ....Xx.........@ 0x0030: 097c 023c 2400 0000 0300 0173 656c 6563 .|.<$......selec 0x0040: 7420 636f 756e 7428 2a29 2066 726f 6d20 t.count(*).from. 0x0050: 7465 7374 2e6d 656d 6265 723b test.member;
connectionTestQuery 가 지정되지 않은 상황.
만약 connectionTestQuery 가 지정되지 않은 상황에서는 아래와 같이 "0x0e" 에 해당하는 Ping 요청이 전달되게 됩니다.
02:28:35.011665 IP fbbbd46ffc0b.34658 > mysql.mysql.mysql: Flags [P.], seq 1277:1282, ack 1351, win 524, options [nop,nop,TS val 2722991198 ecr 163062227], length 5 0x0000: 4500 0039 602a 4000 4006 826b ac12 0003 E..9`*@.@..k.... 0x0010: ac12 0002 8762 0cea 1c0d eed9 061e 1b5c .....b.........\ 0x0020: 8018 020c 5855 0000 0101 080a a24d 8c5e ....XU.......M.^ 0x0030: 09b8 21d3 0100 0000 0e ..!......
https://dev.mysql.com/doc/dev/mysql-server/9.1.0/page_protocol_com_ping.html
MySQL: COM_PING
Check if the server is alive Payload TypeNameDescription int<1> command 0x0E: COM_PING ReturnsOK_Packet See alsomysql_ping, dispatch_command
dev.mysql.com
KeepaliveTime 과 MySQL 의 wait_timeout 관계.
MySQL 은 Idle Connection 을 wait_timeout 으로 지정된 시간까지만 유지합니다.
만약 Idle Connection 이 wait_timeout 시간을 경과하게 되면 Idle Connection 은 강제로 종료됩니다.
MySQL 의 wait_timeout 기본값은 8시간이며, 8시간이 경과한 Idle Connection 은 종료됩니다.
일반적으로 show processlist; 명령어를 통해서 아래와 같은 결과를 확인할 수 있습니다.
show processlist; +----+-----------------+------------------+------+---------+------+------------------------+------------------+ | Id | User | Host | db | Command | Time | State | Info | +----+-----------------+------------------+------+---------+------+------------------------+------------------+ | 5 | event_scheduler | localhost | NULL | Daemon | 5366 | Waiting on empty queue | NULL | | 27 | root | 172.18.0.3:43234 | test | Sleep | 27 | | NULL | | 28 | root | 172.18.0.3:43250 | test | Sleep | 27 | | NULL | | 29 | root | localhost | NULL | Query | 0 | init | show processlist | +----+-----------------+------------------+------+---------+------+------------------------+------------------+ 4 rows in set (0.00 sec)
그리고 Time 이라는 칼럼의 의미하는 값이 Connection 의 지속 시간입니다.
위 결과를 보면 Sleep Command 를 가지는 2개의 Connection 이 Idle Connection 에 해당합니다.
그리고 27초간 Idle Time 이 지속되고 있습니다.
만약 Query 가 실행되어서 Active Connection 으로 변경된다면 이 시간은 0초로 초기화됩니다.
show processlist; +----+-----------------+------------------+------+---------+------+------------------------+------------------+ | Id | User | Host | db | Command | Time | State | Info | +----+-----------------+------------------+------+---------+------+------------------------+------------------+ | 5 | event_scheduler | localhost | NULL | Daemon | 5485 | Waiting on empty queue | NULL | | 27 | root | 172.18.0.3:43234 | test | Sleep | 1 | | NULL | | 28 | root | 172.18.0.3:43250 | test | Sleep | 2 | | NULL | | 29 | root | localhost | NULL | Query | 0 | init | show processlist | +----+-----------------+------------------+------+---------+------+------------------------+------------------+ 4 rows in set (0.00 sec)
Keepalive Time 은 이러한 wait_timeout 으로 인한 Idle Connection 의 강제적인 종료를 방지하고자 지속적인 Query 요청 또는 Ping 요청을 보내는 것을 목적으로 합니다.
Idle Connection 은 Query / Ping 요청을 보내면 Active Connection 으로 상태가 변경되고, Time 이 0 초로 Reset 됩니다.
KeepaliveTime 의 최소값.
HikariCP 의 keepalive Time 의 최소값은 30초로 제한됩니다.
https://github.com/brettwooldridge/HikariCP?utm_source=chatgpt.com
GitHub - brettwooldridge/HikariCP: 光 HikariCP・A solid, high-performance, JDBC connection pool at last.
光 HikariCP・A solid, high-performance, JDBC connection pool at last. - brettwooldridge/HikariCP
github.com
관련 명령어들.
cat <<EOF> /tmp/HikariPoolMonitor.java import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; import java.sql.Connection; import java.sql.Statement; import java.sql.ResultSet; import java.sql.SQLException; public class HikariPoolMonitor { public static void main(String[] args) throws InterruptedException { // HikariCP 설정 HikariConfig config = new HikariConfig(); config.setJdbcUrl("jdbc:mysql://mysql:3306/test?allowPublicKeyRetrieval=true&useSSL=false"); config.setUsername("root"); config.setPassword("1234"); config.setMinimumIdle(2); config.setMaximumPoolSize(5); config.setKeepaliveTime(40000); config.setIdleTimeout(70000); config.setMaxLifetime(1200000); // Hikari DataSource 생성 HikariDataSource dataSource = new HikariDataSource(config); Connection c1 = null; Connection c2 = null; Connection c3 = null; Connection c4 = null; Connection c5 = null; try {c1 = dataSource.getConnection();} catch (SQLException e) {e.printStackTrace();} try {c2 = dataSource.getConnection();} catch (SQLException e) {e.printStackTrace();} try {c3 = dataSource.getConnection();} catch (SQLException e) {e.printStackTrace();} try {c4 = dataSource.getConnection();} catch (SQLException e) {e.printStackTrace();} try {c5 = dataSource.getConnection();} catch (SQLException e) {e.printStackTrace();} try {Thread.sleep(1000L); c1.close();} catch (Exception e) {e.printStackTrace();} try {c2.close();} catch (SQLException e) {e.printStackTrace();} try {c3.close();} catch (SQLException e) {e.printStackTrace();} try {c4.close();} catch (SQLException e) {e.printStackTrace();} try {c5.close();} catch (SQLException e) {e.printStackTrace();} // 5초 단위로 HikariCP 풀 상태를 출력하는 루프 while (true) { printHikariPoolStatus(dataSource); Thread.sleep(5000); // 5초 대기 } // 데이터소스 종료 // dataSource.close(); } // HikariCP 풀 상태 출력 함수 private static void printHikariPoolStatus(HikariDataSource ds) { System.out.println("========== HikariCP Pool 상태 =========="); System.out.println("총 커넥션 수: " + ds.getHikariPoolMXBean().getTotalConnections()); System.out.println("활성 커넥션 수: " + ds.getHikariPoolMXBean().getActiveConnections()); System.out.println("유휴 커넥션 수: " + ds.getHikariPoolMXBean().getIdleConnections()); System.out.println("대기 중인 스레드 수: " + ds.getHikariPoolMXBean().getThreadsAwaitingConnection()); System.out.println("====================================\n"); } } EOF docker network create mysql cat <<EOF> /tmp/my.cnf [mysqld] skip_ssl tls_version=DISABLED EOF docker run -d --platform linux/amd64 --network mysql --name mysql --hostname mysql -v /tmp/my.cnf:/etc/mysql/conf.d/custom.cnf -p 3306:3306 -e MYSQL_ROOT_PASSWORD=1234 mysql:8.0.23 docker run -it --network mysql --rm -v /tmp/HikariPoolMonitor.java:/tmp/HikariPoolMonitor.java openjdk:11 /bin/bash cd /tmp/ wget https://repo1.maven.org/maven2/com/zaxxer/HikariCP/5.1.0/HikariCP-5.1.0.jar wget https://repo1.maven.org/maven2/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar wget https://repo1.maven.org/maven2/org/slf4j/slf4j-simple/1.7.36/slf4j-simple-1.7.36.jar wget https://repo1.maven.org/maven2/com/mysql/mysql-connector-j/8.0.33/mysql-connector-j-8.0.33.jar -P /tmp javac -cp HikariCP-5.1.0.jar:slf4j-api-1.7.36.jar:slf4j-simple-1.7.36.jar:mysql-connector-j-8.0.33.jar HikariPoolMonitor.java java -cp .:HikariCP-5.1.0.jar:slf4j-api-1.7.36.jar:slf4j-simple-1.7.36.jar:mysql-connector-j-8.0.33.jar HikariPoolMonitor create database test; use test; create table test.member (id int primary key not null auto_increment); insert into member values (),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),();
반응형'Java' 카테고리의 다른 글
[HikariCP] idleTimeout 알아보기 (0) 2024.07.18 [HikariCP] connectionTimeout 설정 알아보기 (0) 2024.07.11 [Java Serialization] 여러가지 자바 직렬화 해석 방식들 (0) 2024.07.06 Java ReentrantLock 알아보기 (0) 2024.06.03 [Java] 익명 클래스와 메모리 관계 알아보기 ( Anonymous Class , Method Area ) (0) 2024.06.02