Skip to content

Latest commit

ย 

History

History
300 lines (219 loc) ยท 29.5 KB

mysql-connection-pool.md

File metadata and controls

300 lines (219 loc) ยท 29.5 KB

MySQL Connection Pool ๊ด€๋ฆฌ: HikariCP ์„ค์ • ๋ฐ ํƒ€์ž„์•„์›ƒ ์ฒ˜๋ฆฌ

Connection Pool์ด๋ž€?

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ MySQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€์˜ ํšจ์œจ์ ์ธ ์—ฐ๊ฒฐ์„ ์œ„ํ•ด ์ปค๋„ฅ์…˜ ํ’€์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ปค๋„ฅ์…˜ ํ’€์€ ๋ฏธ๋ฆฌ ์ผ์ •ํ•œ ์ˆ˜์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์„ ์ƒ์„ฑํ•ด ๋‘๊ณ , ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ํ•„์š”ํ•  ๋•Œ๋งˆ๋‹ค ์ด ์—ฐ๊ฒฐ๋“ค์„ ์žฌ์‚ฌ์šฉํ•จ์œผ๋กœ์จ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค๋Š” ๊ธฐ๋ฒ•์ž…๋‹ˆ๋‹ค. ์ด ๋ฐฉ์‹์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€์˜ ์—ฐ๊ฒฐ์„ ๋งค๋ฒˆ ์ƒˆ๋กœ ์ƒ์„ฑํ•˜๋Š” ๋Œ€์‹  ์ด๋ฏธ ์ค€๋น„๋œ ์—ฐ๊ฒฐ์„ ์žฌ์‚ฌ์šฉํ•˜์—ฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์‘๋‹ต ์‹œ๊ฐ„์„ ์ค„์ด๋Š” ๋ฐ ๋งค์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

Java JDBC์™€ HikariCP

Java ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๊ฐ€์žฅ ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” ์ปค๋„ฅ์…˜ ํ’€ ์ค‘ ํ•˜๋‚˜๋Š” HikariCP์ž…๋‹ˆ๋‹ค. HikariCP๋Š” ๊ฐ€๋ณ๊ณ  ๋น ๋ฅธ ์ปค๋„ฅ์…˜ ํ’€๋กœ, ๋Œ€๊ทœ๋ชจ ํŠธ๋ž˜ํ”ฝ์ด ๋ฐœ์ƒํ•˜๋Š” ์ƒํ™ฉ์—์„œ๋„ ํšจ์œจ์ ์ธ ์—ฐ๊ฒฐ ๊ด€๋ฆฌ๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. HikariCP๋Š” HikariPoolMXBean๊ณผ HikariConfigMXBean์ด๋ผ๋Š” JMX(Java Management Extensions)๋ฅผ ํ†ตํ•ด ์ปค๋„ฅ์…˜ ํ’€์˜ ์ƒํƒœ ๋ฐ ์„ค์ •์„ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Spring Boot์—์„œ์˜ HikariCP ์„ค์ •๊ณผ ๊ธฐ๋ณธ๊ฐ’

์„ค์ • ํ•ญ๋ชฉ ์„ค๋ช… ๊ธฐ๋ณธ๊ฐ’
maximum-pool-size ์ปค๋„ฅ์…˜ ํ’€์—์„œ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋Š” ์ตœ๋Œ€ ์ปค๋„ฅ์…˜ ์ˆ˜์ž…๋‹ˆ๋‹ค. ์ด ์ˆ˜์น˜๋ฅผ ์ดˆ๊ณผํ•˜๋Š” ์š”์ฒญ์€ ๋Œ€๊ธฐ ์ƒํƒœ๋กœ ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค. 10
minimum-idle ํ’€์—์„œ ์œ ์ง€ํ•  ์œ ํœด ์ปค๋„ฅ์…˜์˜ ์ตœ์†Œ ๊ฐœ์ˆ˜์ž…๋‹ˆ๋‹ค. ์œ ํœด ์ปค๋„ฅ์…˜์ด ์ด ์ˆ˜์น˜ ์ดํ•˜๋กœ ๋–จ์–ด์ง€๋ฉด ์ƒˆ๋กœ์šด ์ปค๋„ฅ์…˜์ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. maximum-pool-size ๊ฐ’๊ณผ ๋™์ผ
connection-timeout ์ปค๋„ฅ์…˜์„ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด ์Šค๋ ˆ๋“œ๊ฐ€ ๋Œ€๊ธฐํ•  ์ˆ˜ ์žˆ๋Š” ์ตœ๋Œ€ ์‹œ๊ฐ„์ž…๋‹ˆ๋‹ค. ์ด ์‹œ๊ฐ„์ด ์ดˆ๊ณผ๋˜๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. 30,000ms (30์ดˆ)
max-lifetime ์ปค๋„ฅ์…˜์ด ์œ ์ง€๋  ์ˆ˜ ์žˆ๋Š” ์ตœ๋Œ€ ์‹œ๊ฐ„์ž…๋‹ˆ๋‹ค. ์ด ์‹œ๊ฐ„์ด ์ง€๋‚˜๋ฉด ์ปค๋„ฅ์…˜์€ ํ๊ธฐ๋˜๊ณ  ์ƒˆ ์ปค๋„ฅ์…˜์œผ๋กœ ๊ต์ฒด๋ฉ๋‹ˆ๋‹ค. 1,800,000ms (30๋ถ„)
idle-timeout ์œ ํœด ์ƒํƒœ์˜ ์ปค๋„ฅ์…˜์ด ํ’€์—์„œ ์œ ์ง€๋  ์ˆ˜ ์žˆ๋Š” ์ตœ๋Œ€ ์‹œ๊ฐ„์ž…๋‹ˆ๋‹ค. ์ด ์‹œ๊ฐ„์ด ์ง€๋‚˜๋ฉด ์œ ํœด ์ปค๋„ฅ์…˜์ด ํ’€์—์„œ ์ œ๊ฑฐ๋ฉ๋‹ˆ๋‹ค. 600,000ms (10๋ถ„)
leak-detection-threshold ์ง€์ •๋œ ์‹œ๊ฐ„(๋ฐ€๋ฆฌ์ดˆ) ๋™์•ˆ ์‚ฌ์šฉ๋˜์ง€ ์•Š์€ ์ปค๋„ฅ์…˜์„ ๊ฐ์ง€ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ด ์‹œ๊ฐ„์ด ์ง€๋‚˜๋ฉด ์ปค๋„ฅ์…˜ ๋ฆฌํฌ(leak)๋ฅผ ์˜์‹ฌํ•˜๊ณ  ๊ฒฝ๊ณ ๋ฅผ ๋‚จ๊น๋‹ˆ๋‹ค. 0 (๋น„ํ™œ์„ฑํ™”)
pool-name ์ปค๋„ฅ์…˜ ํ’€์˜ ์ด๋ฆ„์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ HikariCP๋Š” ์ž๋™์œผ๋กœ ์ด๋ฆ„์„ ์ƒ์„ฑํ•˜์ง€๋งŒ, ํ•„์š”์— ๋”ฐ๋ผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž๋™ ์ƒ์„ฑ๋œ ์ด๋ฆ„
auto-commit ์ƒˆ ์ปค๋„ฅ์…˜์ด ์ž๋™ ์ปค๋ฐ‹ ๋ชจ๋“œ๋กœ ์‹œ์ž‘ํ• ์ง€๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ ์ฟผ๋ฆฌ ํ›„ ์ž๋™์œผ๋กœ ์ปค๋ฐ‹๋ฉ๋‹ˆ๋‹ค. true
validation-timeout ์ปค๋„ฅ์…˜์ด ์œ ํšจํ•œ์ง€ ๊ฒ€์ฆํ•  ๋•Œ ์‚ฌ์šฉํ•  ์ตœ๋Œ€ ์‹œ๊ฐ„์ž…๋‹ˆ๋‹ค. ์ด ์‹œ๊ฐ„์ด ์ดˆ๊ณผ๋˜๋ฉด ์ปค๋„ฅ์…˜์€ ์œ ํšจํ•˜์ง€ ์•Š๋‹ค๊ณ  ํŒ๋‹จํ•˜๊ณ  ํ๊ธฐ๋ฉ๋‹ˆ๋‹ค. 5,000ms (5์ดˆ)
read-only ์ปค๋„ฅ์…˜์ด ์ฝ๊ธฐ ์ „์šฉ ๋ชจ๋“œ์—์„œ ์ž‘๋™ํ• ์ง€๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค. false
isolate-internal-queries ๋‚ด๋ถ€ ์ฟผ๋ฆฌ(์˜ˆ: ์ปค๋„ฅ์…˜ ํ’€์˜ ์œ ์ง€ ๊ด€๋ฆฌ ์ฟผ๋ฆฌ)๊ฐ€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ฟผ๋ฆฌ์™€ ๊ฒฉ๋ฆฌ๋˜๋Š”์ง€๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. false
allow-pool-suspension ์ปค๋„ฅ์…˜ ํ’€์˜ ์ผ์‹œ ์ •์ง€ ๊ธฐ๋Šฅ์„ ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค. ์ด ์„ค์ •์ด ํ™œ์„ฑํ™”๋˜๋ฉด ํ’€์„ ์ผ์‹œ ์ •์ง€ํ•˜๊ฑฐ๋‚˜ ๋‹ค์‹œ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. false
initialization-fail-timeout ํ’€์„ ์‹œ์ž‘ํ•  ๋•Œ ์ดˆ๊ธฐํ™”์— ์‹คํŒจํ•˜๋Š” ๊ฒฝ์šฐ๋ฅผ ๋Œ€๋น„ํ•œ ํƒ€์ž„์•„์›ƒ ์‹œ๊ฐ„์ž…๋‹ˆ๋‹ค. ์ด ์‹œ๊ฐ„์ด ์ง€๋‚˜๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. 1์ดˆ (1,000ms)

์ปค๋„ฅ์…˜ ํ’€ ์‹œ๋‚˜๋ฆฌ์˜ค ์„ค๋ช…

maximumPoolSize๊ฐ€ 10์ธ ์ปค๋„ฅ์…˜ ํ’€์„ ๊ฐ€์ง„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ, 10๋ช…์˜ ์‚ฌ์šฉ์ž๊ฐ€ ๊ฐ๊ฐ 1์ดˆ์— ํ•œ ๋ฒˆ์”ฉ ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ฐ ์š”์ฒญ์€ ์•ฝ 1์ดˆ๊ฐ€ ์†Œ์š”๋ฉ๋‹ˆ๋‹ค. ์•„๋ž˜ ์‹œ๋‚˜๋ฆฌ์˜ค๋Š” ์ปค๋„ฅ์…˜ ํ’€์˜ ์ƒํƒœ๋ฅผ ๊ฐ ๋‹จ๊ณ„๋ณ„๋กœ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

์ปค๋„ฅ์…˜ ํ’€์˜ ์ฃผ์š” ํ•„๋“œ ๋ฐ ๋™์ž‘ ์‹œ๋‚˜๋ฆฌ์˜ค ๋ถ„์„

  • maximumPoolSize:
    • ์„ค๋ช…: ์ปค๋„ฅ์…˜ ํ’€์—์„œ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ์ตœ๋Œ€ ์ปค๋„ฅ์…˜ ์ˆ˜๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์ด ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ๋Š” 10๊ฐœ๋กœ ์„ค์ •๋˜์–ด ์žˆ์–ด, ๋™์‹œ์— ์ตœ๋Œ€ 10๊ฐœ์˜ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ์ด๋ฏธ์ง€ ์„ค๋ช…: ์ด๋ฏธ์ง€์—์„œ totalConnections = 10์œผ๋กœ ์„ค์ •๋˜์–ด ์žˆ์œผ๋ฉฐ, ์ด๋Š” ์ปค๋„ฅ์…˜ ํ’€์—์„œ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ์ด ์ปค๋„ฅ์…˜์ด 10๊ฐœ์ž„์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
  • activeConnections:
    • ์„ค๋ช…: ํ˜„์žฌ ์š”์ฒญ์„ ์ฒ˜๋ฆฌ ์ค‘์ธ ์ปค๋„ฅ์…˜์˜ ์ˆ˜์ž…๋‹ˆ๋‹ค. ๋™์‹œ ์š”์ฒญ์ด 10๊ฑด ๋ฐœ์ƒํ•˜๋ฉด activeConnections๋Š” 10์ด ๋ฉ๋‹ˆ๋‹ค. ๋” ์ด์ƒ ์—ฌ์œ ๊ฐ€ ์—†๋Š” ์ƒํƒœ์—์„œ ์ถ”๊ฐ€ ์š”์ฒญ์ด ๋“ค์–ด์˜ค๋ฉด ๋Œ€๊ธฐ ์ƒํƒœ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.
    • ์ด๋ฏธ์ง€ ์„ค๋ช…: ์ฒซ ๋ฒˆ์งธ ๊ทธ๋ฆผ์—์„œ activeConnections = 1๋กœ, ํ•œ ๊ฐœ์˜ ์š”์ฒญ์ด ํ™œ์„ฑํ™”๋œ ์ƒํƒœ์ž…๋‹ˆ๋‹ค. ๋‘ ๋ฒˆ์งธ ๊ทธ๋ฆผ์—์„œ๋Š” activeConnections = 5๋กœ, 5๋ช…์ด ๋™์‹œ์— ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์„ธ ๋ฒˆ์งธ ๊ทธ๋ฆผ์—์„œ๋Š” activeConnections = 10์œผ๋กœ, ๋ชจ๋“  ์ปค๋„ฅ์…˜์ด ํ™œ์„ฑํ™”๋˜์–ด ์ถ”๊ฐ€ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†๋Š” ์ƒํƒœ์ž…๋‹ˆ๋‹ค.
  • idleConnections:
    • ์„ค๋ช…: ์œ ํœด ์ƒํƒœ๋กœ ๋Œ€๊ธฐ ์ค‘์ธ ์ปค๋„ฅ์…˜์˜ ์ˆ˜๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์ฒซ ๋ฒˆ์งธ ์š”์ฒญ์ด ์ฒ˜๋ฆฌ๋  ๋•Œ idleConnections๋Š” 9๊ฐœ์ด๋ฉฐ, ๋ชจ๋“  ์ปค๋„ฅ์…˜์ด ํ™œ์„ฑํ™”๋˜๋ฉด idleConnections๋Š” 0์ด ๋ฉ๋‹ˆ๋‹ค.
    • ์ด๋ฏธ์ง€ ์„ค๋ช…: ์ฒซ ๋ฒˆ์งธ ๊ทธ๋ฆผ์—์„œ idleConnections = 9๋กœ, 9๊ฐœ์˜ ์ปค๋„ฅ์…˜์ด ๋Œ€๊ธฐ ์ƒํƒœ์ž…๋‹ˆ๋‹ค. ๋‘ ๋ฒˆ์งธ ๊ทธ๋ฆผ์—์„œ๋Š” idleConnections = 5, ์„ธ ๋ฒˆ์งธ ๊ทธ๋ฆผ์—์„œ๋Š” idleConnections = 0์œผ๋กœ, ๋ชจ๋“  ์ปค๋„ฅ์…˜์ด ์‚ฌ์šฉ ์ค‘์ธ ์ƒํƒœ์ž…๋‹ˆ๋‹ค.
  • totalConnections:
    • ์„ค๋ช…: ์ปค๋„ฅ์…˜ ํ’€์—์„œ ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ๋Š” ์ด ์ปค๋„ฅ์…˜ ์ˆ˜๋กœ, activeConnections์™€ idleConnections์˜ ํ•ฉ์ž…๋‹ˆ๋‹ค. ์ด ๊ฐ’์€ maximumPoolSize ๋‚ด์—์„œ ์œ ์ง€๋˜๋ฉฐ, ๋™์‹œ ์š”์ฒญ์ด ๋งŽ์„์ˆ˜๋ก idleConnections๊ฐ€ ์ค„์–ด๋“ญ๋‹ˆ๋‹ค.
    • ์ด๋ฏธ์ง€ ์„ค๋ช…: ์„ธ ๊ฐœ์˜ ๊ทธ๋ฆผ ๋ชจ๋‘ totalConnections = 10์œผ๋กœ, ์ด๋Š” ์ปค๋„ฅ์…˜ ํ’€์—์„œ ๊ด€๋ฆฌํ•˜๋Š” ์ปค๋„ฅ์…˜์ด ์ด 10๊ฐœ์ž„์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
  • threadsAwaitingConnection:
    • ์„ค๋ช…: ์ปค๋„ฅ์…˜์ด ๋ชจ๋‘ ์‚ฌ์šฉ ์ค‘์ผ ๋•Œ ๋Œ€๊ธฐ ์ค‘์ธ ์š”์ฒญ์˜ ์ˆ˜๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, 10๋ช…์˜ ์‚ฌ์šฉ์ž๊ฐ€ ๋ชจ๋‘ ์ปค๋„ฅ์…˜์„ ์‚ฌ์šฉ ์ค‘์ผ ๋•Œ ์ถ”๊ฐ€ ์š”์ฒญ์ด ๋ฐœ์ƒํ•˜๋ฉด, ๊ทธ ์š”์ฒญ์€ ๋Œ€๊ธฐ ์ƒํƒœ๋กœ ๋“ค์–ด๊ฐ€ threadsAwaitingConnection์ด ์ฆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
    • ์ด๋ฏธ์ง€ ์„ค๋ช…: ๋งˆ์ง€๋ง‰ ๊ทธ๋ฆผ์—์„œ๋Š” ๋ชจ๋“  ์ปค๋„ฅ์…˜์ด ์‚ฌ์šฉ ์ค‘์ด๊ธฐ ๋•Œ๋ฌธ์—, ์ถ”๊ฐ€ ์š”์ฒญ์ด ๋ฐœ์ƒํ•˜๋ฉด ๋Œ€๊ธฐ ์ƒํƒœ๋กœ ๋“ค์–ด๊ฐ€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
  • connectionTimeout:
    • ์„ค๋ช…: ๋Œ€๊ธฐ ์ค‘์ธ ์š”์ฒญ์ด ์ปค๋„ฅ์…˜์„ ์–ป๊ธฐ ์œ„ํ•ด ๊ธฐ๋‹ค๋ฆด ์ˆ˜ ์žˆ๋Š” ์ตœ๋Œ€ ์‹œ๊ฐ„์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, connectionTimeout์ด 2์ดˆ๋กœ ์„ค์ •๋œ ๊ฒฝ์šฐ, ๋Œ€๊ธฐ ์ค‘์ธ ์š”์ฒญ์ด 2์ดˆ ๋‚ด์— ์ปค๋„ฅ์…˜์„ ํ• ๋‹น๋ฐ›์ง€ ๋ชปํ•˜๋ฉด ์š”์ฒญ์€ ์‹คํŒจํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
    • ์ด๋ฏธ์ง€ ์„ค๋ช…: ๋งˆ์ง€๋ง‰ ๊ทธ๋ฆผ์—์„œ ๋ชจ๋“  ์ปค๋„ฅ์…˜์ด ์‚ฌ์šฉ ์ค‘์ธ ์ƒํƒœ์—์„œ ์ถ”๊ฐ€ ์š”์ฒญ์ด ๋“ค์–ด์˜ค๋ฉด, connectionTimeout ๋‚ด์— ์ปค๋„ฅ์…˜์„ ํ• ๋‹น๋ฐ›์ง€ ๋ชปํ•  ๊ฒฝ์šฐ ํ•ด๋‹น ์š”์ฒญ์€ ์‹คํŒจํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
  • validationTimeout:
    • ์„ค๋ช…: ํ’€์—์„œ ์ปค๋„ฅ์…˜์„ ๋นŒ๋ ค์˜ฌ ๋•Œ ํ•ด๋‹น ์ปค๋„ฅ์…˜์ด ์œ ํšจํ•œ์ง€ ํ™•์ธํ•˜๋Š” ์‹œ๊ฐ„์ž…๋‹ˆ๋‹ค. ์ด ์‹œ๊ฐ„์ด ์ดˆ๊ณผ๋˜๋ฉด ํ•ด๋‹น ์ปค๋„ฅ์…˜์€ ์‚ฌ์šฉ๋˜์ง€ ์•Š๊ณ  ์ƒˆ๋กœ์šด ์ปค๋„ฅ์…˜์ด ํ• ๋‹น๋ฉ๋‹ˆ๋‹ค.
    • ์ด๋ฏธ์ง€ ์„ค๋ช…: ์œ ํœด ์ƒํƒœ๋กœ ์˜ค๋ž˜ ์žˆ๋˜ ์ปค๋„ฅ์…˜์€ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ์—์„œ ์‹คํŒจํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด ๊ฒฝ์šฐ ์ƒˆ๋กœ์šด ์ปค๋„ฅ์…˜์ด ํ• ๋‹น๋ฉ๋‹ˆ๋‹ค. ์ด๋ฏธ์ง€์—์„œ๋Š” ์œ ํœด ์ƒํƒœ์˜ ์ปค๋„ฅ์…˜๋“ค์ด ๋Œ€๊ธฐ ์ค‘์ธ ์ƒํƒœ๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

HikariCP ์„ค์ • ๋ฐ ์ƒํƒœ ์ธก์ • ์ƒ˜ํ”Œ ์ฝ”๋“œ

Spring Boot ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ HikariCP๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. HikariCP๋Š” Spring Boot์—์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ์ปค๋„ฅ์…˜ ํ’€๋กœ, ์„ค์ •์„ ํ†ตํ•ด ๋‹ค์–‘ํ•œ ์ปค๋„ฅ์…˜ ๊ด€๋ฆฌ ์˜ต์…˜์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ, HikariCP์˜ ์ƒํƒœ๋ฅผ ์ธก์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์ถ”๊ฐ€ํ•˜์—ฌ ์ปค๋„ฅ์…˜ ํ’€์˜ ํšจ์œจ์ ์ธ ๊ด€๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

HikariCP Properties ์„ค์ •

spring:
    datasource:
        hikari:
            maximum-pool-size: 10           # ์ตœ๋Œ€ ์ปค๋„ฅ์…˜ ์ˆ˜
            minimum-idle: 10                # ์ตœ์†Œ ์œ ํœด ์ปค๋„ฅ์…˜ ์ˆ˜
            connection-timeout: 30000       # ์ปค๋„ฅ์…˜์„ ๊ฐ€์ ธ์˜ฌ ๋•Œ ๋Œ€๊ธฐํ•  ์ตœ๋Œ€ ์‹œ๊ฐ„ (๋ฐ€๋ฆฌ์ดˆ)
            max-lifetime: 1800000           # ์ปค๋„ฅ์…˜์ด ์œ ์ง€๋  ์ตœ๋Œ€ ์‹œ๊ฐ„ (๋ฐ€๋ฆฌ์ดˆ)
            idle-timeout: 600000            # ์œ ํœด ์ปค๋„ฅ์…˜์ด ์œ ์ง€๋  ์ตœ๋Œ€ ์‹œ๊ฐ„ (๋ฐ€๋ฆฌ์ดˆ)
            leak-detection-threshold: 2000  # ์ปค๋„ฅ์…˜ ๋ฆฌํฌ๋ฅผ ๊ฐ์ง€ํ•  ๊ธฐ์ค€ ์‹œ๊ฐ„ (๋ฐ€๋ฆฌ์ดˆ)
            pool-name: Sample-HikariPool    # ์ปค๋„ฅ์…˜ ํ’€ ์ด๋ฆ„
            auto-commit: true               # ์ž๋™ ์ปค๋ฐ‹ ์—ฌ๋ถ€
            validation-timeout: 5000        # ์ปค๋„ฅ์…˜ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ์œ„ํ•œ ์ตœ๋Œ€ ์‹œ๊ฐ„ (๋ฐ€๋ฆฌ์ดˆ)
            read-only: false                # ์ฝ๊ธฐ ์ „์šฉ ๋ชจ๋“œ ์—ฌ๋ถ€
            isolate-internal-queries: false # ๋‚ด๋ถ€ ์ฟผ๋ฆฌ ๊ฒฉ๋ฆฌ ์—ฌ๋ถ€
            allow-pool-suspension: false    # ์ปค๋„ฅ์…˜ ํ’€ ์ผ์‹œ ์ •์ง€ ํ—ˆ์šฉ ์—ฌ๋ถ€
            initialization-fail-timeout: 1  # ์ดˆ๊ธฐํ™” ์‹คํŒจ ์‹œ ํƒ€์ž„์•„์›ƒ (๋ฐ€๋ฆฌ์ดˆ)

HikariCP ์ƒํƒœ ์ธก์ • ์ฝ”๋“œ

@Service
class SampleService(
    private val dataSource: DataSource,
    private val memberRepository: MemberRepository
) {

    private val log = LoggerFactory.getLogger(javaClass)!!

    @Transactional
    fun getMember(): Member {
        val member = memberRepository.findById(Random.nextInt(1, 101).toLong()).get()
        runBlocking { delay(1000) }
        val targetDataSource = dataSource.unwrap(HikariDataSource::class.java)
        val hikariDataSource = targetDataSource as HikariDataSource
        val hikariPoolMXBean = hikariDataSource.hikariPoolMXBean
        val hikariConfigMXBean = hikariDataSource.hikariConfigMXBean
        val log =
            """
            totalConnections : ${hikariPoolMXBean.totalConnections}
            activeConnections : ${hikariPoolMXBean.activeConnections}
            idleConnections : ${hikariPoolMXBean.idleConnections}
            threadsAwaitingConnection : ${hikariPoolMXBean.threadsAwaitingConnection}
            """.trimIndent()

        this.log.info(log)

        return member
    }
}

์ด ์ฝ”๋“œ์—์„œ๋Š” ๋จผ์ € DataSource๋ฅผ HikariDataSource๋กœ ๋ณ€ํ™˜ํ•œ ํ›„, HikariPoolMXBean๊ณผ HikariConfigMXBean์„ ์‚ฌ์šฉํ•˜์—ฌ ์ปค๋„ฅ์…˜ ํ’€์˜ ์ƒํƒœ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ด ์ปค๋„ฅ์…˜ ์ˆ˜, ํ™œ์„ฑ ์ปค๋„ฅ์…˜ ์ˆ˜, ์œ ํœด ์ปค๋„ฅ์…˜ ์ˆ˜, ๊ทธ๋ฆฌ๊ณ  ๋Œ€๊ธฐ ์ค‘์ธ ์Šค๋ ˆ๋“œ ์ˆ˜์™€ ๊ฐ™์€ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. ๋˜ํ•œ, runBlocking { delay(1000) }์„ ์‚ฌ์šฉํ•˜์—ฌ 1์ดˆ๊ฐ„์˜ ์ง€์—ฐ์„ ์ถ”๊ฐ€ํ•จ์œผ๋กœ์จ, ์‹ค์ œ ์š”์ฒญ์ด ์ฒ˜๋ฆฌ๋˜๋Š” ๋™์•ˆ ์ปค๋„ฅ์…˜ ํ’€์˜ ์ƒํƒœ๋ฅผ ๋ณด๋‹ค ๋ช…ํ™•ํ•˜๊ฒŒ ๋ชจ๋‹ˆํ„ฐ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ, ์ด๋Ÿฌํ•œ ์ปค๋„ฅ์…˜ ํ’€์˜ ์ƒํƒœ๋ฅผ ๋กœ๊ทธ๋กœ ์ถœ๋ ฅํ•˜์—ฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์„ฑ๋Šฅ์„ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๊ณ , ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์„ฑ๋Šฅ์„ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์ •๋ณด๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

Connection Pool ์ธก์ •

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ปค๋„ฅ์…˜ ํ’€์„ ์‚ฌ์šฉํ•  ๋•Œ, ์ปค๋„ฅ์…˜ ํ’€์˜ ์ƒํƒœ๋ฅผ ์ง€์†์ ์œผ๋กœ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๋Š” ๊ฒƒ์€ ๋งค์šฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ์•„๋ž˜์™€ ๊ฐ™์€ ๋กœ๊ทธ๋Š” **10 TPS (์ดˆ๋‹น ํŠธ๋žœ์žญ์…˜)**๋ฅผ ์ง€์†์ ์œผ๋กœ ์œ ์ง€ํ•  ๋•Œ ๋ฐœ์ƒํ•œ ๋กœ๊ทธ์ž…๋‹ˆ๋‹ค. ์ด๋•Œ ํ‰๊ท  ์‘๋‹ต ์‹œ๊ฐ„์€ ์•ฝ 1,000ms๋กœ ๋‚˜ํƒ€๋‚˜๋ฉฐ, ์ด๋Š” TPS ์ˆ˜์ค€์„ ๊ณ ๋ คํ–ˆ์„ ๋•Œ ์‹œ์Šคํ…œ์ด ์ ์ • ์ˆ˜์ค€์—์„œ ์ž‘๋™ํ•˜๊ณ  ์žˆ์Œ์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

  • ๋กœ๊ทธ 1:

    • totalConnections = 10
    • activeConnections = 7
    • idleConnections = 3
    • threadsAwaitingConnection = 0

    ์ด ์ƒํƒœ๋Š” ์ด 10๊ฐœ์˜ ์ปค๋„ฅ์…˜ ์ค‘ 7๊ฐœ๊ฐ€ ํ™œ์„ฑํ™”๋˜์–ด ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, 3๊ฐœ์˜ ์œ ํœด ์ปค๋„ฅ์…˜์ด ๋Œ€๊ธฐ ์ค‘์ธ ์ƒํ™ฉ์ž…๋‹ˆ๋‹ค. ๋ชจ๋“  ์š”์ฒญ์ด ์›ํ™œํ•˜๊ฒŒ ์ฒ˜๋ฆฌ๋˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๋Œ€๊ธฐ ์ค‘์ธ ์Šค๋ ˆ๋“œ๋Š” ์—†์Šต๋‹ˆ๋‹ค.

  • ๋กœ๊ทธ 2:

    • totalConnections = 10
    • activeConnections = 10
    • idleConnections = 0
    • threadsAwaitingConnection = 4

    ์ด ์ƒํƒœ๋Š” ๋ชจ๋“  10๊ฐœ์˜ ์ปค๋„ฅ์…˜์ด ํ™œ์„ฑํ™”๋˜์–ด ์š”์ฒญ์„ ์ฒ˜๋ฆฌ ์ค‘์ด๋ฉฐ, ๋” ์ด์ƒ ์œ ํœด ์ปค๋„ฅ์…˜์ด ๋‚จ์•„์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋•Œ 4๊ฐœ์˜ ์ถ”๊ฐ€ ์š”์ฒญ์ด ๋“ค์–ด์™€ ๋Œ€๊ธฐ ์ค‘์ž…๋‹ˆ๋‹ค. threadsAwaitingConnection ๊ฐ’์ด 4๋กœ ์ฆ๊ฐ€ํ•œ ์ด์œ ๋Š”, ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ์œ ํœด ์ปค๋„ฅ์…˜์ด ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์ปค๋„ฅ์…˜ ํ’€ ๋™์ž‘ ๋ฐ ํƒ€์ž„์•„์›ƒ ๋ฐœ์ƒ

์ปค๋„ฅ์…˜ ํ’€์ด ์„ค์ •๋œ maximumPoolSize๋งŒํผ ํ™œ์„ฑํ™”๋œ ๊ฒฝ์šฐ, ๊ทธ ์ดํ›„์— ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์€ ๋Œ€๊ธฐ ์ƒํƒœ์— ๋“ค์–ด๊ฐ€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋•Œ ๋Œ€๊ธฐ ์‹œ๊ฐ„์ด ๊ธธ์–ด์งˆ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋Ÿฌํ•œ ๋Œ€๊ธฐ ์‹œ๊ฐ„์ด ๋„ˆ๋ฌด ๊ธธ์–ด์ง€๋ฉด ํƒ€์ž„์•„์›ƒ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํƒ€์ž„์•„์›ƒ์ด ๋ฐœ์ƒํ•˜๋Š” ์ฃผ์š” ์›์ธ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

connection-timeout์€ ์ปค๋„ฅ์…˜์„ ์–ป๊ธฐ ์œ„ํ•ด ์Šค๋ ˆ๋“œ๊ฐ€ ๋Œ€๊ธฐํ•  ์ˆ˜ ์žˆ๋Š” ์ตœ๋Œ€ ์‹œ๊ฐ„์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, connection-timeout์ด 30์ดˆ๋กœ ์„ค์ •๋˜์–ด ์žˆ๋‹ค๋ฉด, ์ปค๋„ฅ์…˜ ํ’€์ด ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ปค๋„ฅ์…˜์„ 30์ดˆ ๋™์•ˆ ์ œ๊ณตํ•˜์ง€ ๋ชปํ•  ๊ฒฝ์šฐ ํƒ€์ž„์•„์›ƒ์ด ๋ฐœ์ƒํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด ์„ค์ •์€ ๋Œ€๊ธฐ ์ค‘์ธ ์š”์ฒญ์ด ์–ผ๋งˆ ๋™์•ˆ ๊ธฐ๋‹ค๋ฆด ์ˆ˜ ์žˆ๋Š”์ง€๋ฅผ ์ œํ•œํ•ฉ๋‹ˆ๋‹ค.

์ปค๋„ฅ์…˜ ํ’€์€ ํ•œ์ •๋œ ์ž์›์„ ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜์—ฌ ์‹œ์Šคํ…œ์˜ ์•ˆ์ •์„ฑ์„ ์œ ์ง€ํ•˜๋Š” ์ข‹์€ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜, ๋งŒ์•ฝ ์š”์ฒญ๋Ÿ‰์ด ์„ค์ •๋œ maximumPoolSize๋ฅผ ์ดˆ๊ณผํ•˜๊ฒŒ ๋˜๋ฉด ๋Œ€๊ธฐ ์ƒํƒœ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ƒํ™ฉ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์ ์ ˆํ•œ ํƒ€์ž„์•„์›ƒ ๊ฐ’์„ ์„ค์ •ํ•˜๊ณ , ํ•„์š”์— ๋”ฐ๋ผ ํ’€ ํฌ๊ธฐ๋ฅผ ์กฐ์ •ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

connection-timeout ์„ค์ •๊ณผ TPS ์ฆ๊ฐ€๋กœ ์ธํ•œ ์˜ค๋ฅ˜ ๋ฐœ์ƒ

spring:
    datasource:
        hikari:
            maximum-pool-size: 10         # ์ตœ๋Œ€ ์ปค๋„ฅ์…˜ ์ˆ˜
            minimum-idle: 10              # ์ตœ์†Œ ์œ ํœด ์ปค๋„ฅ์…˜ ์ˆ˜
            connection-timeout: 250       # ์ปค๋„ฅ์…˜์„ ๊ฐ€์ ธ์˜ฌ ๋•Œ ๋Œ€๊ธฐํ•  ์ตœ๋Œ€ ์‹œ๊ฐ„ (๋ฐ€๋ฆฌ์ดˆ)

์œ„ ์„ค์ •์—์„œ connection-timeout์„ 250ms๋กœ ์ง€์ •ํ•œ ๊ฒฝ์šฐ, TPS๊ฐ€ 10์„ ์ดˆ๊ณผํ•˜๊ฒŒ ๋˜๋ฉด threadsAwaitingConnection์— ๋Œ€๊ธฐํ•˜๋Š” ์‹œ๊ฐ„์ด 250ms๋ฅผ ๋„˜์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•˜๋ฉด, ์ปค๋„ฅ์…˜ ํ’€์€ ์„ค์ •๋œ ๋Œ€๊ธฐ ์‹œ๊ฐ„๋ณด๋‹ค ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์— ํƒ€์ž„์•„์›ƒ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ด๋ฏธ์ง€์—์„œ์™€ ๊ฐ™์ด, RPS(Request Per Second)๊ฐ€ 10 ์ด์ƒ์ผ ๋•Œ ์ปค๋„ฅ์…˜ ํ’€์˜ ํ•œ๊ณ„๋กœ ์ธํ•ด ๋Œ€๊ธฐ ์ค‘์ธ ์š”์ฒญ์ด ๋ฐœ์ƒํ•˜๊ณ , ๊ทธ ๋Œ€๊ธฐ ์‹œ๊ฐ„์ด 250ms๋ฅผ ์ดˆ๊ณผํ•˜๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์ด๋•Œ Failures/s๊ฐ€ ์ฆ๊ฐ€ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ํƒ€์ž„์•„์›ƒ ์„ค์ •๊ณผ ๊ด€๋ จ์ด ์žˆ์œผ๋ฉฐ, ์ปค๋„ฅ์…˜ ํ’€์˜ ์ž์› ํ•œ๊ณ„์™€ ์ฒ˜๋ฆฌ๋Ÿ‰์„ ์ ์ ˆํžˆ ๋งž์ถฐ์•ผ ํ•˜๋Š” ์ด์œ ๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€ ์˜ˆ์‹œ:

java.sql.SQLTransientConnectionException: Sample-HikariPool - Connection is not available, request timed out after 251ms.
	at com.zaxxer.hikari.pool.HikariPool.createTimeoutException(HikariPool.java:696) ~[HikariCP-4.0.3.jar:na]
	at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:197) 

์ด ์˜ค๋ฅ˜๋Š” ๋Œ€๊ธฐ ์‹œ๊ฐ„์ด ์„ค์ •๋œ connection-timeout์„ ์ดˆ๊ณผํ–ˆ์Œ์„ ์˜๋ฏธํ•˜๋ฉฐ, ์ปค๋„ฅ์…˜ ํ’€์ด ์ถ”๊ฐ€ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์„ ๊ณ ๋ คํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Connection Pool ๋ฌธ์ œ ํ•ด๊ฒฐ๋ฐฉ๋ฒ•

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ Connection Pool์€ ์•ˆ์ •์ ์ธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์„ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐ ๋งค์šฐ ์ค‘์š”ํ•œ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์‹œ์Šคํ…œ ๋ถ€ํ•˜๊ฐ€ ๋†’๊ฑฐ๋‚˜ ์„ค์ •์ด ์ ์ ˆํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ, ์ปค๋„ฅ์…˜ ํ’€์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๋กœ ์ธํ•ด ์„ฑ๋Šฅ ์ €ํ•˜๋‚˜ ํƒ€์ž„์•„์›ƒ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ช‡ ๊ฐ€์ง€ ํ•ต์‹ฌ์ ์ธ ์ ‘๊ทผ ๋ฐฉ์‹์„ ์ทจํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ์ฟผ๋ฆฌ ์ตœ์ ํ™”: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„ฑ๋Šฅ ๋ฌธ์ œ๋Š” ์ข…์ข… ๋น„ํšจ์œจ์ ์ธ ์ฟผ๋ฆฌ๋กœ ์ธํ•ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์ฟผ๋ฆฌ ์ตœ์ ํ™”๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์‘๋‹ต ์‹œ๊ฐ„์„ ์ค„์ด๊ณ , ์ปค๋„ฅ์…˜์ด ์˜ค๋žซ๋™์•ˆ ์ ์œ ๋˜๋Š” ์ƒํ™ฉ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋Š” ์ค‘์š”ํ•œ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ์ธ๋ฑ์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ๋ณต์žกํ•œ ์ฟผ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๋‹จ์ˆœํ™”ํ•˜๋Š” ๊ฒƒ ๋“ฑ์ด ์ด์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค.
  2. connection-timeout ์‹œ๊ฐ„ ์กฐ์ •: ์ปค๋„ฅ์…˜ ํƒ€์ž„์•„์›ƒ์€ ๋Œ€๊ธฐ ์ค‘์ธ ์š”์ฒญ์ด ์ปค๋„ฅ์…˜์„ ์–ป๊ธฐ ์œ„ํ•ด ์–ผ๋งˆ๋‚˜ ์˜ค๋žœ ์‹œ๊ฐ„ ๊ธฐ๋‹ค๋ฆด ์ˆ˜ ์žˆ๋Š”์ง€๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด ์‹œ๊ฐ„์„ ์ ์ ˆํžˆ ์„ค์ •ํ•จ์œผ๋กœ์จ ๋Œ€๊ธฐ ์ค‘์ธ ์š”์ฒญ๋“ค์ด ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋„ˆ๋ฌด ์งง์€ ํƒ€์ž„์•„์›ƒ์€ ์˜ค๋ฅ˜๋ฅผ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ๊ณ , ๋„ˆ๋ฌด ๊ธด ํƒ€์ž„์•„์›ƒ์€ ์‘๋‹ต ์ง€์—ฐ์„ ์ดˆ๋ž˜ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ์ƒํ™ฉ์— ๋งž๊ฒŒ ํƒ€์ž„์•„์›ƒ์„ ์กฐ์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  3. maximum-pool-size ์ฆ๊ฐ€: ์˜ˆ์ƒ๋˜๋Š” ํŠธ๋ž˜ํ”ฝ์— ๋งž์ถฐ ์ปค๋„ฅ์…˜ ํ’€์˜ ์ตœ๋Œ€ ํฌ๊ธฐ๋ฅผ ๋Š˜๋ฆผ์œผ๋กœ์จ ๋™์‹œ ์š”์ฒญ ์ฒ˜๋ฆฌ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ž์› ๋‚ญ๋น„๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์‹œ์Šคํ…œ์˜ ๋ฉ”๋ชจ๋ฆฌ์™€ CPU ์‚ฌ์šฉ๋Ÿ‰์„ ์‹ ์ค‘ํ•˜๊ฒŒ ๊ณ ๋ คํ•˜์—ฌ ์ตœ์ ์˜ ํฌ๊ธฐ๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

์ด์™€ ๊ฐ™์€ ๋ฐฉ๋ฒ•์„ ์ ์ ˆํžˆ ์ ์šฉํ•˜๋ฉด Connection Pool ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ณ , ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์„ฑ๋Šฅ๊ณผ ์•ˆ์ •์„ฑ์„ ํฌ๊ฒŒ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์—์„œ๋Š” ์ด ์„ธ ๊ฐ€์ง€ ์ ‘๊ทผ ๋ฐฉ๋ฒ•์„ ๊ตฌ์ฒด์ ์œผ๋กœ ๋‹ค๋ฃจ๊ณ , ์‹ค์ œ ์ ์šฉ ์‚ฌ๋ก€๋ฅผ ํ†ตํ•ด ์„ฑ๋Šฅ ์ตœ์ ํ™” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

์ฟผ๋ฆฌ ์ตœ์ ํ™”

์ฟผ๋ฆฌ ์ตœ์ ํ™”๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„ฑ๋Šฅ ํ–ฅ์ƒ์— ์žˆ์–ด ์ค‘์š”ํ•œ ๋‹จ๊ณ„์ž…๋‹ˆ๋‹ค. ํŠนํžˆ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ activeConnections๊ฐ€ ๋น ๋ฅด๊ฒŒ ์‘๋‹ตํ•˜์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ, ๊ทธ ์›์ธ์ด ๋ณต์žกํ•œ ์ฟผ๋ฆฌ ์ฒ˜๋ฆฌ์— ์žˆ๋‹ค๋ฉด ์ฟผ๋ฆฌ ์ตœ์ ํ™”๋ฅผ ํ†ตํ•ด ์„ฑ๋Šฅ์„ ํฌ๊ฒŒ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž˜๋ชป ์„ค๊ณ„๋œ ์ฟผ๋ฆฌ๋‚˜ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๊ธด ์‹คํ–‰ ์‹œ๊ฐ„์„ ๊ฐ€์ง„ ์ฟผ๋ฆฌ๋Š” ์‹œ์Šคํ…œ ์ „๋ฐ˜์˜ ์„ฑ๋Šฅ์— ์˜ํ–ฅ์„ ๋ฏธ์น˜๊ณ , ์ปค๋„ฅ์…˜ ํ’€์˜ ์ž์›์„ ์˜ค๋ž˜ ์ ์œ ํ•˜๊ฒŒ ๋˜์–ด ๋Œ€๊ธฐ ์ค‘์ธ ์š”์ฒญ๋“ค์ด ์ง€์—ฐ๋˜๋Š” ์ƒํ™ฉ์„ ์ดˆ๋ž˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ์ฟผ๋ฆฌ๋ฅผ ์ตœ์ ํ™”ํ•จ์œผ๋กœ์จ ์‘๋‹ต ์†๋„๋ฅผ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

@Transactional
fun getMember(): Member {
    val member = memberRepository.findById(Random.nextInt(1, 101).toLong()).get()
    // runBlocking { delay(1000) } ๋ธ”๋กํ‚น ์ฝ”๋“œ ์ œ๊ฑฐ
    ...
    return member
}

์œ„ ์ฝ”๋“œ์—์„œ ๋ถˆํ•„์š”ํ•œ ๋ธ”๋กœํ‚น ์ฝ”๋“œ์ธ runBlocking { delay(1000) }๋ฅผ ์ œ๊ฑฐํ•จ์œผ๋กœ์จ ์ฟผ๋ฆฌ ์‹คํ–‰ ์ง€์—ฐ์„ ์—†์•ด์Šต๋‹ˆ๋‹ค. ์ด์™€ ๊ฐ™์ด, ์ฟผ๋ฆฌ ์ตœ์ ํ™”๋Š” ๋‹จ์ˆœํžˆ ์ฝ”๋“œ ๋‚ด์˜ ๋ธ”๋กœํ‚น ์š”์†Œ๋ฅผ ์ œ๊ฑฐํ•˜๋Š” ๊ฒƒ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, ์ธ๋ฑ์Šค ์ถ”๊ฐ€, ๋ณต์žกํ•œ ์กฐ์ธ ๊ตฌ์กฐ ๋‹จ์ˆœํ™”, ์บ์‹ฑ ๋“ฑ์„ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋Œ€ํ•œ ๋ถ€ํ•˜๋ฅผ ์ค„์ด๋Š” ๋ฐฉ๋ฒ•๋„ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ตœ์ ํ™” ์ž‘์—…์„ ํ†ตํ•ด ์ฟผ๋ฆฌ ์‹คํ–‰ ์‹œ๊ฐ„์ด ์ค„์–ด๋“ค๋ฉด ์ปค๋„ฅ์…˜์ด ๋” ๋นจ๋ฆฌ ๋ฐ˜ํ™˜๋˜๊ณ , ๋Œ€๊ธฐ ์ค‘์ธ ์š”์ฒญ์ด ๋น ๋ฅด๊ฒŒ ์ฒ˜๋ฆฌ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฟผ๋ฆฌ ์ตœ์ ํ™”๋ฅผ ํ†ตํ•ด ์„ฑ๋Šฅ์ด ํ–ฅ์ƒ๋˜๋ฉด, connection-timeout์ด 250ms๋กœ ์„ค์ •๋œ ์ƒํ™ฉ์—์„œ๋„ RPS๊ฐ€ 20์ธ ๊ฒฝ์šฐ์ฒ˜๋Ÿผ ๋†’์€ ์š”์ฒญ ์ฒ˜๋ฆฌ๋Ÿ‰์—์„œ๋„ ํƒ€์ž„์•„์›ƒ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์ฟผ๋ฆฌ๊ฐ€ ์ตœ์ ํ™”๋˜๋ฉด ์ปค๋„ฅ์…˜์ด ๋” ๋น ๋ฅด๊ฒŒ ๋ฐ˜ํ™˜๋˜๊ธฐ ๋•Œ๋ฌธ์—, ์ปค๋„ฅ์…˜ ํ’€ ๋‚ด์—์„œ ๋” ๋งŽ์€ ์š”์ฒญ์„ ๋™์‹œ์— ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์ตœ์ ํ™”๋œ ์ฟผ๋ฆฌ๋Š” ์ปค๋„ฅ์…˜ ์ ์œ  ์‹œ๊ฐ„์„ ์ค„์—ฌ connection-timeout ์„ค์ •์˜ ์ œํ•œ์„ ๋„˜์ง€ ์•Š๋„๋ก ๋„์™€์ฃผ๋ฉฐ, ๊ฒฐ๊ณผ์ ์œผ๋กœ ๋” ๋งŽ์€ ํŠธ๋žœ์žญ์…˜์„ ์•ˆ์ •์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, ์ฟผ๋ฆฌ ์ตœ์ ํ™”๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„ฑ๋Šฅ์„ ์œ ์ง€ํ•˜๊ณ  ํ–ฅ์ƒ์‹œํ‚ค๋Š” ์ค‘์š”ํ•œ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

๊ฒฐ๋ก ์ ์œผ๋กœ, ์ฟผ๋ฆฌ ์ตœ์ ํ™”๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„ฑ๋Šฅ ๊ฐœ์„ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, ์ปค๋„ฅ์…˜ ํ’€ ์ž์› ๊ด€๋ฆฌ์—๋„ ๋งค์šฐ ์ค‘์š”ํ•œ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ๋ถˆํ•„์š”ํ•œ ๋Œ€๊ธฐ ์‹œ๊ฐ„์„ ์ค„์ด๊ณ , ์‹œ์Šคํ…œ์ด ๊ณ ๋ถ€ํ•˜ ์ƒํ™ฉ์—์„œ๋„ ์›ํ™œํ•˜๊ฒŒ ์ž‘๋™ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋•์Šต๋‹ˆ๋‹ค.

connection-timeout ์‹œ๊ฐ„ ์กฐ์ •

connection-timeout ์„ค์ •์€ ๋Œ€๊ธฐ ์ค‘์ธ ์š”์ฒญ์ด ์ปค๋„ฅ์…˜์„ ์–ป๊ธฐ ์œ„ํ•ด ๊ธฐ๋‹ค๋ฆด ์ˆ˜ ์žˆ๋Š” ์‹œ๊ฐ„์„ ์กฐ์ •ํ•˜๋Š” ์ค‘์š”ํ•œ ์š”์†Œ์ž…๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์š”์ฒญ๋Ÿ‰์ด ๋งŽ์•„ maximumPoolSize์— ๋„๋‹ฌํ–ˆ์„ ๋•Œ, connection-timeout์„ ์ ์ ˆํžˆ ๋Š˜๋ ค์ฃผ๋ฉด ๋Œ€๊ธฐ ์ค‘์ธ ์š”์ฒญ์ด ์ปค๋„ฅ์…˜์„ ํ• ๋‹น๋ฐ›๊ธฐ๊นŒ์ง€ ๋” ์˜ค๋žœ ์‹œ๊ฐ„์„ ํ—ˆ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, connection-timeout์„ 250ms์—์„œ 2,500ms๋กœ ๋Š˜๋ฆฌ๋ฉด, ์ปค๋„ฅ์…˜ ๋ฐ˜ํ™˜ ๋Œ€๊ธฐ ์‹œ๊ฐ„์„ ๋” ๊ธธ๊ฒŒ ์„ค์ •ํ•จ์œผ๋กœ์จ ํƒ€์ž„์•„์›ƒ ์˜ค๋ฅ˜๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ, ๋„ˆ๋ฌด ๊ธด ๋Œ€๊ธฐ ์‹œ๊ฐ„์„ ์„ค์ •ํ•˜๋ฉด ๊ทธ๋งŒํผ ์‘๋‹ต ์‹œ๊ฐ„์ด ์ง€์—ฐ๋  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์‹ ์ค‘ํ•˜๊ฒŒ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์•„๋ž˜๋Š” connection-timeout์„ 2,500ms๋กœ ์„ค์ •ํ•˜๊ณ  ํ…Œ์ŠคํŠธํ•œ ์„ค์ • ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค:

spring:
    datasource:
        hikari:
            maximum-pool-size: 10         # ์ตœ๋Œ€ ์ปค๋„ฅ์…˜ ์ˆ˜
            minimum-idle: 10              # ์ตœ์†Œ ์œ ํœด ์ปค๋„ฅ์…˜ ์ˆ˜
            connection-timeout: 2500      # ์ปค๋„ฅ์…˜์„ ๊ฐ€์ ธ์˜ฌ ๋•Œ ๋Œ€๊ธฐํ•  ์ตœ๋Œ€ ์‹œ๊ฐ„ (๋ฐ€๋ฆฌ์ดˆ)

์ด ์„ค์ •์—์„œ, delay(1000)๋Š” ์œ ์ง€ํ•˜๋ฉด์„œ connection-timeout์„ 2,500ms๋กœ ๋ณ€๊ฒฝํ•œ ํ›„ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ๋Š” ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค:

totalConnections : 10
maximumPoolSize : 10
activeConnections : 10
idleConnections : 0
threadsAwaitingConnection : 20
  • totalConnections: 10๊ฐœ ์ปค๋„ฅ์…˜์ด ๋ชจ๋‘ ์‚ฌ์šฉ ์ค‘์ž…๋‹ˆ๋‹ค.
  • maximumPoolSize: ์„ค์ •๋œ ์ตœ๋Œ€ ์ปค๋„ฅ์…˜ ์ˆ˜๋Š” 10๊ฐœ์ž…๋‹ˆ๋‹ค.
  • activeConnections: ํ˜„์žฌ 10๊ฐœ์˜ ์ปค๋„ฅ์…˜์ด ํ™œ์„ฑํ™”๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
  • idleConnections: ์œ ํœด ์ปค๋„ฅ์…˜์ด ์—†์œผ๋ฉฐ, ๋ชจ๋“  ์ปค๋„ฅ์…˜์ด ์‚ฌ์šฉ ์ค‘์ž…๋‹ˆ๋‹ค.
  • threadsAwaitingConnection: 20๊ฐœ์˜ ์š”์ฒญ์ด ๋Œ€๊ธฐ ์ค‘์ž…๋‹ˆ๋‹ค.

connection-timeout ์„ค์ •์ด 2,500ms๋กœ ๋ณ€๊ฒฝ๋จ์— ๋”ฐ๋ผ, threadsAwaitingConnection์—์„œ ๋Œ€๊ธฐํ•˜๋Š” ์‹œ๊ฐ„์ด ๊ธธ์–ด์กŒ์Šต๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ์ ์œผ๋กœ ํƒ€์ž„์•„์›ƒ ์˜ค๋ฅ˜๋Š” ๋ฐœ์ƒํ•˜์ง€ ์•Š์•˜์ง€๋งŒ, ์‘๋‹ต ์‹œ๊ฐ„์ด ๋” ๊ธธ์–ด์กŒ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๊ฐ ์š”์ฒญ์— ๋Œ€ํ•ด delay(1000)์œผ๋กœ ์ธํ•œ 1,000ms์˜ ๋ธ”๋กœํ‚น ์‹œ๊ฐ„๊ณผ threadsAwaitingConnection์—์„œ ๋Œ€๊ธฐํ•œ ์‹œ๊ฐ„์ด ํ•ฉ์ณ์ ธ ์‘๋‹ต ์‹œ๊ฐ„์ด ๋А๋ ค์ง„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด๋Ÿฐ ๊ฒฝ์šฐ, ํƒ€์ž„์•„์›ƒ์„ ๊ธธ๊ฒŒ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์€ ํƒ€์ž„์•„์›ƒ ์˜ค๋ฅ˜๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๋™์‹œ์— ์‘๋‹ต ์†๋„๊ฐ€ ์ €ํ•˜๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, connection-timeout์€ ์š”์ฒญ์˜ ํŠน์„ฑ๊ณผ ํŠธ๋ž˜ํ”ฝ ํŒจํ„ด์— ๋งž์ถ”์–ด ์ ์ ˆํ•œ ๊ฐ’์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ๋งค์šฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

maximum-pool-size ์ฆ๊ฐ€

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๋™์‹œ ์š”์ฒญ ์ˆ˜๊ฐ€ ๋งŽ์•„์งˆ ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒ๋œ๋‹ค๋ฉด, maximum-pool-size๋ฅผ ๋Š˜๋ ค ์ปค๋„ฅ์…˜ ํ’€์—์„œ ๋” ๋งŽ์€ ์ปค๋„ฅ์…˜์„ ์ƒ์„ฑํ•˜๊ณ  ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ํŠธ๋ž˜ํ”ฝ์ด ์˜ˆ์ƒ๋ณด๋‹ค ๋งŽ์•„์ง€๊ฑฐ๋‚˜, ๋™์‹œ์„ฑ ์ฒ˜๋ฆฌ๊ฐ€ ๋งŽ์ด ์š”๊ตฌ๋˜๋Š” ์ƒํ™ฉ์—์„œ๋Š” ์ปค๋„ฅ์…˜ ํ’€ ํฌ๊ธฐ๋ฅผ ๋Š˜๋ ค์ฃผ๋Š” ๊ฒƒ์ด ์œ ๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋” ๋งŽ์€ ์š”์ฒญ์„ ๋™์‹œ์— ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜, ๋ฌด์ž‘์ • ํ’€ ํฌ๊ธฐ๋ฅผ ํฌ๊ฒŒ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์€ ์ž์› ๋‚ญ๋น„๋ฅผ ์ดˆ๋ž˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ปค๋„ฅ์…˜ ํ’€ ํฌ๊ธฐ๊ฐ€ ์ปค์ง€๋ฉด ๋” ๋งŽ์€ ๋ฉ”๋ชจ๋ฆฌ์™€ CPU๊ฐ€ ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์‹œ์Šคํ…œ์˜ ์ž์› ์‚ฌ์šฉ๋Ÿ‰์„ ์‹ ์ค‘ํžˆ ๊ณ ๋ คํ•œ ํ›„์— ์กฐ์ •ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, maximum-pool-size๋ฅผ 100์œผ๋กœ ์„ค์ •ํ•˜๊ณ , 1,000ms ๋Œ€๊ธฐ ์ฝ”๋“œ๋ฅผ ๋‹ค์‹œ ํ™œ์„ฑํ™”์‹œํ‚ค๋ฉฐ connection-timeout์„ 250ms๋กœ ์œ ์ง€ํ–ˆ์Œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ , ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š” ์ƒํ™ฉ์„ ๊ฐ€์ •ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

@Transactional
fun getMember(): Member {
    val member = memberRepository.findById(Random.nextInt(1, 101).toLong()).get()
    runBlocking { delay(1000) }  // 1,000ms ๋Œ€๊ธฐ
    ...
    return member
}

์ด ์ฝ”๋“œ์—์„œ๋Š” runBlocking { delay(1000) }๋ฅผ ํ†ตํ•ด ๊ฐ ์š”์ฒญ๋งˆ๋‹ค 1์ดˆ์˜ ์ง€์—ฐ์„ ๋ฐœ์ƒ์‹œํ‚ค๊ณ  ์žˆ์ง€๋งŒ, maximum-pool-size๋ฅผ ์ถฉ๋ถ„ํžˆ ๋†’๊ฒŒ ์„ค์ •ํ•จ์œผ๋กœ์จ ๋™์‹œ ์š”์ฒญ์ด ๋ชฐ๋ฆฌ๋Š” ์ƒํ™ฉ์—์„œ๋„ ํƒ€์ž„์•„์›ƒ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์™€ ๊ฐ™์€ ๋กœ๊ทธ๋ฅผ ํ†ตํ•ด ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

totalConnections : 30
maximumPoolSize : 100
activeConnections : 13
idleConnections : 17
  • totalConnections: ํ˜„์žฌ ์ปค๋„ฅ์…˜ ํ’€์—์„œ ๊ด€๋ฆฌ๋˜๊ณ  ์žˆ๋Š” ์ปค๋„ฅ์…˜์˜ ์ด ๊ฐœ์ˆ˜๋กœ, ํ˜„์žฌ 30๊ฐœ๊ฐ€ ํ• ๋‹น๋˜์–ด ์žˆ๋Š” ์ƒํƒœ์ž…๋‹ˆ๋‹ค.
  • maximumPoolSize: ์ปค๋„ฅ์…˜ ํ’€์—์„œ ์„ค์ •๋œ ์ตœ๋Œ€ ์ปค๋„ฅ์…˜ ์ˆ˜๋Š” 100์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ, ๋ชจ๋“  ์ปค๋„ฅ์…˜์ด ํ•„์š”ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— 100๊นŒ์ง€ ์ฐจ์ง€ ์•Š๊ณ  ์žˆ๋Š” ์ƒํ™ฉ์ž…๋‹ˆ๋‹ค.
  • activeConnections: ํ˜„์žฌ ์š”์ฒญ์„ ์ฒ˜๋ฆฌ ์ค‘์ธ ํ™œ์„ฑ ์ปค๋„ฅ์…˜ ์ˆ˜๋Š” 13๊ฐœ์ž…๋‹ˆ๋‹ค.
  • idleConnections: ์œ ํœด ์ƒํƒœ๋กœ ๋Œ€๊ธฐ ์ค‘์ธ ์ปค๋„ฅ์…˜ ์ˆ˜๋Š” 17๊ฐœ๋กœ, ์š”์ฒญ์ด ์ถ”๊ฐ€๋กœ ๋“ค์–ด์˜ค๋ฉด ์ด ์ปค๋„ฅ์…˜๋“ค์ด ํ™œ์„ฑํ™”๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ์ƒํ™ฉ์—์„œ๋Š” maximumPoolSize๊ฐ€ 100์œผ๋กœ ์„ค์ •๋˜์–ด ์žˆ์ง€๋งŒ, ๋ชจ๋“  ์ปค๋„ฅ์…˜์ด ์‚ฌ์šฉ ์ค‘์ด์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ž์› ๋‚ญ๋น„๋ฅผ ์ตœ์†Œํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์š”์ฒญ์ด ๋ชฐ๋ฆฌ์ง€ ์•Š๋Š” ์ƒํƒœ์—์„œ๋Š” activeConnections๊ฐ€ 13๊ฐœ์— ๋จธ๋ฌด๋ฅด๊ณ , ๋‚˜๋จธ์ง€ 17๊ฐœ๋Š” ์œ ํœด ์ƒํƒœ๋กœ ๋‚จ์•„์žˆ์Šต๋‹ˆ๋‹ค. ์ด์ฒ˜๋Ÿผ ์ตœ๋Œ€ ์ปค๋„ฅ์…˜ ์ˆ˜๋Š” ์„ค์ •ํ–ˆ์ง€๋งŒ, ํ•„์š”ํ•  ๋•Œ๋งŒ ์ปค๋„ฅ์…˜์ด ํ™œ์„ฑํ™”๋˜๊ณ  ๋‚˜๋จธ์ง€๋Š” ์œ ํœด ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ํšจ์œจ์ ์ธ ์ž์› ๊ด€๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ, maximum-pool-size๋Š” ํŠธ๋ž˜ํ”ฝ์ด ๋ชฐ๋ฆด ๊ฒฝ์šฐ๋ฅผ ๋Œ€๋น„ํ•ด ์ถฉ๋ถ„ํžˆ ํฐ ๊ฐ’์œผ๋กœ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์‹œ์Šคํ…œ ์ž์›์— ๋ถ€๋‹ด์„ ์ฃผ์ง€ ์•Š๋„๋ก ์‹ค์ œ ํŠธ๋ž˜ํ”ฝ๊ณผ ์ž์› ์‚ฌ์šฉ๋Ÿ‰์„ ๋ถ„์„ํ•˜์—ฌ ์ ์ ˆํ•œ ๊ฐ’์œผ๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

๊ฒฐ๋ก 

HikariCP๋ฅผ ์‚ฌ์šฉํ•œ MySQL ์ปค๋„ฅ์…˜ ํ’€ ๊ด€๋ฆฌ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„ฑ๋Šฅ ์ตœ์ ํ™”์˜ ํ•ต์‹ฌ ์š”์†Œ์ž…๋‹ˆ๋‹ค. ์ ์ ˆํ•œ ์ปค๋„ฅ์…˜ ํ’€ ์„ค์ •์„ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€์˜ ์—ฐ๊ฒฐ์„ ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ณ , ๋ถˆํ•„์š”ํ•œ ์—ฐ๊ฒฐ ์žฌ์ƒ์„ฑ์„ ํ”ผํ•˜๋ฉฐ, ์‘๋‹ต ์‹œ๊ฐ„์„ ๋‹จ์ถ•ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜, maximumPoolSize์™€ connection-timeout๊ณผ ๊ฐ™์€ ์„ค์ •์ด ์ ์ ˆํ•˜์ง€ ์•Š์œผ๋ฉด, ํŠธ๋ž˜ํ”ฝ์ด ์ฆ๊ฐ€ํ•  ๋•Œ ์ปค๋„ฅ์…˜ ํ’€์—์„œ ๋Œ€๊ธฐ ์‹œ๊ฐ„์ด ๋Š˜์–ด๋‚˜๊ฑฐ๋‚˜ ํƒ€์ž„์•„์›ƒ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ณ  ์‹œ์Šคํ…œ ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”ํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ค‘์š”ํ•œ ํฌ์ธํŠธ๋ฅผ ๊ธฐ์–ตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  1. ์ฟผ๋ฆฌ ์ตœ์ ํ™”: ์ฟผ๋ฆฌ์˜ ์„ฑ๋Šฅ์ด ๋А๋ฆด ๊ฒฝ์šฐ activeConnections๊ฐ€ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ์˜ค๋ž˜ ์ ์œ ๋˜๋ฉฐ, ์ „์ฒด ์‹œ์Šคํ…œ์˜ ์„ฑ๋Šฅ์„ ์ €ํ•˜์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฟผ๋ฆฌ๋ฅผ ์ตœ์ ํ™”ํ•˜์—ฌ ์ปค๋„ฅ์…˜์„ ๋น ๋ฅด๊ฒŒ ๋ฐ˜ํ™˜ํ•˜๋ฉด ๋Œ€๊ธฐ ์ค‘์ธ ์š”์ฒญ๋„ ์‹ ์†ํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. maximum-pool-size ์„ค์ •: maximum-pool-size๋Š” ๋™์‹œ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ์ตœ๋Œ€ ์š”์ฒญ ์ˆ˜๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค. ํŠธ๋ž˜ํ”ฝ ์˜ˆ์ธก์— ๋งž์ถฐ ์ ์ ˆํžˆ ํ’€ ํฌ๊ธฐ๋ฅผ ๋Š˜๋ฆฌ๋Š” ๊ฒƒ์€ ์ค‘์š”ํ•˜์ง€๋งŒ, ์ž์› ๋‚ญ๋น„๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ๋„ˆ๋ฌด ํฌ๊ฒŒ ์„ค์ •ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ํ•„์š”ํ•  ๋•Œ๋งŒ ์ปค๋„ฅ์…˜์ด ํ™œ์„ฑํ™”๋˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ž์›์„ ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  3. connection-timeout ์„ค์ •: connection-timeout ๊ฐ’์€ ๋Œ€๊ธฐ ์ค‘์ธ ์š”์ฒญ์ด ์ปค๋„ฅ์…˜์„ ์–ป๊ธฐ ์œ„ํ•ด ๊ธฐ๋‹ค๋ฆด ์ˆ˜ ์žˆ๋Š” ์ตœ๋Œ€ ์‹œ๊ฐ„์„ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฐ’์„ ๋„ˆ๋ฌด ๋‚ฎ๊ฒŒ ์„ค์ •ํ•˜๋ฉด ํŠธ๋ž˜ํ”ฝ์ด ๋ชฐ๋ฆด ๋•Œ ํƒ€์ž„์•„์›ƒ ์˜ค๋ฅ˜๊ฐ€ ์ž์ฃผ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋ฐ˜๋Œ€๋กœ ๋„ˆ๋ฌด ๊ธธ๊ฒŒ ์„ค์ •ํ•˜๋ฉด ์‘๋‹ต ์‹œ๊ฐ„์ด ์ง€์—ฐ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํŠธ๋ž˜ํ”ฝ ํŒจํ„ด์— ๋งž์ถฐ ์ ์ ˆํ•œ ๊ฐ’์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.
  4. TPS ๋ชจ๋‹ˆํ„ฐ๋ง: ์ดˆ๋‹น ์ฒ˜๋ฆฌ๋Ÿ‰(TPS)์„ ์ง€์†์ ์œผ๋กœ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๊ณ , ํŠธ๋ž˜ํ”ฝ ํŒจํ„ด์„ ๊ธฐ๋ฐ˜์œผ๋กœ HikariCP ์„ค์ •์„ ์กฐ์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋‹ค์–‘ํ•œ ๋ถ€ํ•˜ ์ƒํ™ฉ์—์„œ๋„ ์›ํ™œํ•˜๊ฒŒ ์ž‘๋™ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

์ตœ์ข…์ ์œผ๋กœ, ์ปค๋„ฅ์…˜ ํ’€ ์„ค์ •์„ ์กฐ์ •ํ•  ๋•Œ๋Š” ํŠธ๋ž˜ํ”ฝ ํŒจํ„ด๊ณผ ์‹œ์Šคํ…œ ์ž์›์„ ๊ณ ๋ คํ•˜์—ฌ ์ตœ์ ํ™”๋œ ๊ฐ’์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ํ•„์ˆ˜์ ์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์‘๋‹ต ์†๋„ ์ง€์—ฐ ๋ฐ ํƒ€์ž„์•„์›ƒ ์˜ค๋ฅ˜๋ฅผ ์ตœ์†Œํ™”ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์•ˆ์ •์ ์ธ ์‹œ์Šคํ…œ ์šด์˜๊ณผ ํ•จ๊ป˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์„ฑ๋Šฅ์„ ๊ทน๋Œ€ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.