6๊ฐ์ง ๋ก๋๋ฐธ๋ฐ์ฑ ์๊ณ ๋ฆฌ์ฆ์ ์ง์ ๊ตฌํํ๊ณ , 3๊ฐ์ง ์๋๋ฆฌ์ค์์ ์ฒด๊ณ์ ์ผ๋ก ์ฑ๋ฅ์ ๋น๊ตํ ํ๋ก์ ํธ
"์ด๋ค ๋ก๋๋ฐธ๋ฐ์ฑ ์๊ณ ๋ฆฌ์ฆ์ด ๊ฐ์ฅ ์ข์๊ฐ?"๋ผ๋ ์ง๋ฌธ์ ๋ฐ์ดํฐ ๊ธฐ๋ฐ์ผ๋ก ๋ตํ๊ธฐ ์ํ ํ๋ก์ ํธ์ ๋๋ค.
6๊ฐ์ง ์๊ณ ๋ฆฌ์ฆ์ Spring Boot๋ก ์ง์ ๊ตฌํํ๊ณ , Docker ๊ธฐ๋ฐ 4๋ ์๋ฒ ํ๊ฒฝ์์ K6 ๋ถํ ํ ์คํธ๋ฅผ ์ํํ์ต๋๋ค. Prometheus + Grafana๋ก 8๊ฐ ๋ฉํธ๋ฆญ์ ์ค์๊ฐ ์์งํ์ฌ ์๊ณ ๋ฆฌ์ฆ๋ณ ์ฑ๋ฅ ํน์ฑ, ์ฅ์ ๋์๋ ฅ, ๋ถํ ๋ถ์ฐ ํจํด์ ์ ๋์ ์ผ๋ก ๋น๊ตํ์ต๋๋ค.
- Least Connections๊ฐ RPS, ์๋ต์๊ฐ, ๋ถ์ฐ ๊ท ๋ฑ์ฑ ๋ชจ๋์์ 1์๋ฅผ ๊ธฐ๋ก
- Least Response Time์์ ์ค๋ ธ์ฐ๋ณผ ํจ๊ณผ ๋ฐ๊ฒฌ โ ์ด๋ก ์ ์ต์ ์๊ณ ๋ฆฌ์ฆ์ด ์ค์ ๋ก๋ ๋จ์ผ ์ฅ์ ์ ์ ์์ฑ
- IP Hash๊ฐ ์ฅ์ ๋์ ์๋ฌ์จ 0.00%(3๊ฑด/41,320๊ฑด)์ผ๋ก ์ฌ์ค์ ๋ฌด์ค๋จ ๋ฌ์ฑ
- ๋ฝํ๋ฆฌ ๋์์ฑ ์ ์ด ์ค๊ณ ๋ฐ blocking I/O ํ๊ฒฝ์์์ ๋ณ๋ชฉ ๋ถ์
| ๋ถ๋ฅ | ๊ธฐ์ |
|---|---|
| ๋ก๋๋ฐธ๋ฐ์ | Spring Boot, Java 21, WebClient |
| ๋ฐฑ์๋ ์๋ฒ | Docker Compose (4๊ฐ ์ปจํ ์ด๋) |
| ๋ถํ ํ ์คํธ | K6 |
| ๋ชจ๋ํฐ๋ง | Prometheus, Grafana, Micrometer |
| ๋์์ฑ ์ ์ด | AtomicInteger, volatile, ConcurrentHashMap, ConcurrentSkipListMap, ThreadLocal, CopyOnWriteArrayList |
| ์๊ณ ๋ฆฌ์ฆ | ๋ถ๋ฅ | ํต์ฌ ์๋ฆฌ |
|---|---|---|
| Round Robin | ์ ์ | ์์ฐจ์ ์๋ฒ ์ ํ |
| Weighted Round Robin | ์ ์ | ๊ฐ์ค์น ๊ธฐ๋ฐ ๋น๋ก ๋ถ๋ฐฐ (6:3:2:1) |
| Least Connections | ๋์ | ํ์ฌ ํ์ฑ ์ฐ๊ฒฐ ์ ์ต์์ธ ์๋ฒ ์ ํ |
| IP Hash | ํด์ | ํด๋ผ์ด์ธํธ IP ํด์๋ก ์๋ฒ ๊ณ ์ + ์บ์ ๋งคํ |
| Consistent Hashing | ํด์ | ํด์ ๋ง + ๊ฐ์ ๋ ธ๋(150๊ฐ)๋ก ์ต์ ์ฌ๋ฐฐ์น |
| Least Response Time | ๋์ | ํ๊ท ์๋ต์๊ฐ ์ต์ ์๋ฒ ์ ํ (Circular Buffer) |
| ์๊ณ ๋ฆฌ์ฆ | RPS | avg (ms) | Active Conn ๋ถํฌ |
|---|---|---|---|
| Round Robin | 281.9 | 253.58 | 4 / 11 / 22 / 36 |
| Weighted RR | 387.4 | 157.10 | 6 / 14 / 18 / 16 |
| Least Connections | 421.0 | 136.58 | 14 / 14 / 14 / 14 |
| IP Hash | 281.9 | 253.61 | 2 / 13 / 19 / 32 |
| Consistent Hashing | 279.5 | 256.64 | ์ ์ฌ ํจํด |
| Least Response Time | 640.4* | 55.68* | 35 / 0 / 0 / 0 |
*LRT๋ server-1์ 100% ์ง์ค โ ๋ก๋๋ฐธ๋ฐ์ฑ์ด ์๋ ๋จ์ผ ์๋ฒ ์ ํ
| ์๊ณ ๋ฆฌ์ฆ | RPS | ์๋ฌ์จ | ์๋ฌ ๊ฑด์ | RPS ํ๋ฝํญ |
|---|---|---|---|---|
| Round Robin | 229.7 | 0.83% | 345 | 18.5% |
| Weighted RR | 280.7 | 0.52% | 265 | 27.5% |
| Least Connections | 288.8 | 0.61% | 319 | 31.4% |
| IP Hash | 228.8 | 0.00% | 3 | 18.8% |
| Consistent Hashing | 227.0 | 0.36% | 150 | 18.8% |
| Least Response Time | 422.4* | 0.03% | 23 | 34.0% |
LC๋ ์ฒ๋ฆฌ์๊ฐ์ ์ง์ ์ธก์ ํ์ง ์์ง๋ง, ๋น ๋ฅธ ์๋ฒ๊ฐ ์ฐ๊ฒฐ์ ๋นจ๋ฆฌ ํด์ โ ํญ์ ์ต์ ์ฐ๊ฒฐ ์ ์ง โ ์์ฐ์ค๋ฝ๊ฒ ๋ ๋ง์ ์์ฒญ ์ฒ๋ฆฌ. Active Connections๊ฐ 14/14/14/14๋ก ์๋ฒฝํ ๊ท ๋ฑ ๋ถ์ฐ์ ์ด๋ฃจ๋ฉด์ ๋์์ **์ต๊ณ RPS(421.0)**๋ฅผ ๋ฌ์ฑํ๋ค.
Least Response Time์ด ๊ฐ์ฅ ๋น ๋ฅธ ์๋ฒ์ ํธ๋ํฝ์ 100% ์ง์ค์์ผ ์ฌ์ค์ ๋ก๋๋ฐธ๋ฐ์ฑ์ด ๋์ํ์ง ์๋ ํ์์ ๋ฐ๊ฒฌํ๋ค. ์ฅ์ ๋ฐ์ ์์๋ ์ ๋ฆผ์ด server-2๋ก ์ด์ ๋ ๋ฟ(Active Connections: 0/100/0/0), ๊ทผ๋ณธ์ ์ผ๋ก ํด๊ฒฐ๋์ง ์์๋ค.
์ ์: server-1์ 100% โ ์ฅ์ ๋ฐ์ โ server-2์ 100% (์ ๋ฆผ ์ด์ )
์ฑ๋ฅ(RPS)์์๋ Round Robin๊ณผ ๋์ผํ์ง๋ง, ์ฅ์ ์ ์๋ฌ 3๊ฑด(0.00%)์ผ๋ก ์ฌ์ค์ ๋ฌด์ค๋จ์ ๋ฌ์ฑํ๋ค. ์บ์ ๋งคํ(ipServerMapping.compute())์์ unhealthy ์๋ฒ๋ฅผ ์ฆ์ ๊ฐ์งํ๊ณ ์ฌ์ ํํ๊ธฐ ๋๋ฌธ์ด๋ค.
๋ชจ๋ ์๊ณ ๋ฆฌ์ฆ์์ p95 โ 502ms๋ก ์๋ ด. ๊ฐ์ฅ ๋๋ฆฐ ์๋ฒ(500ms)๋ก ๊ฐ๋ ์์ฒญ์ด ํญ์ ์กด์ฌํ๊ธฐ ๋๋ฌธ. ์๊ณ ๋ฆฌ์ฆ ๊ฐ ์ฐจ์ด๋ avg, med, RPS์์ ๋๋ฌ๋๋ค.
synchronized ๋์ ๋ฝํ๋ฆฌ(lock-free) ๊ธฐ๋ฐ์ผ๋ก ์ค๊ณํ์ฌ ์ปจํ
์คํธ ์ค์์นญ์ ์ต์ํํ๋ค.
| ๊ตฌ์กฐ | ์ ์ฉ ์์น | ์ ํ ์ด์ |
|---|---|---|
| AtomicInteger (CAS) | RR/WRR ์ธ๋ฑ์ค | ๋จ์ผ ์นด์ดํฐ์ ์์์ ์ฆ๊ฐ |
| volatile | ์๋ฒ ๋ฆฌ์คํธ ์ฐธ์กฐ | ๋ฉํฐ์ค๋ ๋ ๊ฐ ๋ฉ๋ชจ๋ฆฌ ๊ฐ์์ฑ ๋ณด์ฅ |
| ConcurrentHashMap | IP Hash ์บ์ | ํค๋ณ ๋ ๋ฆฝ ๋ฝ์ผ๋ก ๊ฒฝํฉ ์ต์ํ |
| ConcurrentSkipListMap | CH ํด์ ๋ง | ์ ๋ ฌ๋ ๊ตฌ์กฐ์ ๋์ ์ ๊ทผ |
| ThreadLocal | ์๊ฐ ํฌ๋งทํฐ | ์ค๋ ๋๋ณ ๋ ๋ฆฝ ์ธ์คํด์ค |
| Copy-on-Write | ์๋ฒ ๋ฆฌ์คํธ ๋ณ๊ฒฝ | ์ฝ๊ธฐ >> ์ฐ๊ธฐ์ธ ๊ตฌ์กฐ์ ์ต์ |
์ฑ๋ฅ ๊ฒ์ฆ: VU 400(8,900 RPS) ํ๊ฒฝ์์ synchronized ๋๋น 3% ์ด๋ด ์ฐจ์ด. ํ์ฌ ๊ตฌ์กฐ์์๋ WebClient.block()์ ๋คํธ์ํฌ I/O๊ฐ ๋ณ๋ชฉ์ด์ด์ ์๊ณ ๋ฆฌ์ฆ ์ ํ ๊ตฌ๊ฐ(๋๋ ธ~๋ง์ดํฌ๋ก์ด)์ ๊ฒฝํฉ์ด ์ ์ฒด ์ฑ๋ฅ์ ๋ฏธ์น๋ ์ํฅ์ด 0.01% ๋ฏธ๋ง. Nginx์ฒ๋ผ non-blocking ์ด๋ฒคํธ ๋ฃจํ ๊ธฐ๋ฐ์์๋ ๋ฝํ๋ฆฌ ์ค๊ณ๊ฐ ์ ์๋ฏธํด์ง๋ค.
Prometheus + Grafana ๊ธฐ๋ฐ 8๊ฐ ์ปค์คํ ๋ฉํธ๋ฆญ ์ค์๊ฐ ์์ง:
| ๋ฉํธ๋ฆญ | ์ค๋ช |
|---|---|
requests_total |
์๊ณ ๋ฆฌ์ฆ/์๋ฒ๋ณ ์ด ์์ฒญ ์ |
response_time_seconds |
์๋ฒ๋ณ ์๋ต์๊ฐ ํ์คํ ๊ทธ๋จ |
algorithm_duration_seconds |
์๊ณ ๋ฆฌ์ฆ ์ ํ ์์์๊ฐ |
active_connections |
์๋ฒ๋ณ ํ์ฌ ํ์ฑ ์ฐ๊ฒฐ ์ |
errors_total |
์๋ฌ ์ ํ๋ณ ์นด์ดํธ |
server_health |
์๋ฒ ํฌ์ค ์ํ (0/1) |
backend_selection_total |
์๋ฒ ์ ํ ํ์ |
docker-compose up -dcd monitoring
docker-compose up -d./gradlew bootRun# Steady Load
k6 run k6/steady_load.js
# Burst
k6 run k6/burst_load.js
# Server Failure (ํ
์คํธ ์ค docker stop web-server-1)
k6 run k6/server_failure.js- Grafana: http://localhost:3000
- Prometheus: http://localhost:9090
| ์ํฉ | ์ถ์ฒ ์๊ณ ๋ฆฌ์ฆ | ๊ทผ๊ฑฐ |
|---|---|---|
| ์๋ฒ ์คํ ๋์ผ | Round Robin | ๊ตฌํ ๋จ์, ๊ท ๋ฑ ๋ถ๋ฐฐ |
| ์๋ฒ ์คํ ์์ด | Weighted RR | RR ๋๋น RPS 37%โ |
| ๋ฒ์ฉ ์น ์๋น์ค | Least Connections | RPSยท์๋ต์๊ฐยท๊ท ๋ฑ์ฑ ๋ชจ๋ 1์ |
| ์ธ์ ์ ์ง ํ์ | IP Hash | ์ฅ์ ๋์ ์๋ฌ์จ 0.00% |
| ์๋ฒ ์์ฃผ ๋ณ๊ฒฝ | Consistent Hashing | ์ต์ ์ฌ๋ฐฐ์น |
- ์ฌ์๋ ๋ก์ง: ์์ฒญ ์คํจ ์ ๋ค๋ฅธ ์๋ฒ๋ก 1ํ ์ฌ์๋ํ์ฌ ์๋ฌ์จ ์ถ๊ฐ ๊ฐ์
- LRT ์ค๋ ธ์ฐ๋ณผ ๋ฐฉ์ง: ์๋ต์๊ฐ ร ํ์ฑ์ฐ๊ฒฐ์ ๋ณตํฉ ์ ์ ๋์
- ML ๊ธฐ๋ฐ ์๊ณ ๋ฆฌ์ฆ: ์ค์๊ฐ ๋ฉํธ๋ฆญ ๊ธฐ๋ฐ ๋์ ์๊ณ ๋ฆฌ์ฆ ์ ํ
