๐Ÿ’ป ๊ฐœ๋ฐœ/๐ŸŽธ ETC

๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ: ์œ ์ € ํ–‰๋™ ๊ธฐ๋ฐ˜ ์‹œ๋‚˜๋ฆฌ์˜ค๋กœ ์‹œ์Šคํ…œ ํ•œ๊ณ„ ์ธก์ •๊ณผ SLA, SLO ๊ฒ€์ฆ

EastShine_ 2024. 11. 29. 01:23

 

๋“ค์–ด๊ฐ€๋ฉฐ

๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ๋Š” ์‹œ์Šคํ…œ์˜ ์ตœ๋Œ€ ์ฒ˜๋ฆฌ๋Ÿ‰(TPS), ์•ˆ์ •์„ฑ, SLA(์„œ๋น„์Šค ์ˆ˜์ค€ ๊ณ„์•ฝ) ๋ฐ SLO(์„œ๋น„์Šค ์ˆ˜์ค€ ๋ชฉํ‘œ)๋ฅผ ๊ฒ€์ฆํ•˜๋Š” ์ค‘์š”ํ•œ ๊ณผ์ •์ž…๋‹ˆ๋‹ค. ์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ์ฝ˜์„œํŠธ ์˜ˆ์•ฝ ์„œ๋น„์Šค์—์„œ ์œ ์ € ํ–‰๋™์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ ๋‘ ๊ฐ€์ง€ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์ค‘์‹ฌ์œผ๋กœ, Docker ํ™˜๊ฒฝ์—์„œ ์ž์›์„ ์กฐ์ ˆํ•˜๋ฉฐ ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•œ ๋‚ด์šฉ์„ ์ •๋ฆฌํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

 

 

1. ํ…Œ์ŠคํŠธ ์‹œ๋‚˜๋ฆฌ์˜ค ์„ค๊ณ„

์œ ์ €์˜ ํ–‰๋™์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋‘ ๊ฐ€์ง€ ํ…Œ์ŠคํŠธ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์„ค๊ณ„ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ฐ๊ฐ์˜ ์‹œ๋‚˜๋ฆฌ์˜ค๋Š” ์‹œ์Šคํ…œ์˜ ์„œ๋กœ ๋‹ค๋ฅธ ์ƒํƒœ(์œ ์ € ๋น„ํ™œ์„ฑ/์œ ์ € ํ™œ์„ฑ)๋ฅผ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์œ„ํ•ด ์„ ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

- ์‹œ๋‚˜๋ฆฌ์˜ค 1 : ์œ ์ € ๋Œ€๊ธฐ์—ด ๋น„ํ™œ์„ฑ

  • ๋ชฉํ‘œ: ๋Œ€๊ธฐ์—ด ์‹œ์Šคํ…œ์—์„œ ํ† ํฐ ๋ฐœ๊ธ‰ ๋ฐ ์ƒํƒœ ์กฐํšŒ์˜ ์ฒ˜๋ฆฌ๋Ÿ‰ ์ธก์ •
  • ํ–‰๋™ ํ๋ฆ„
    1. ์œ ์ €๊ฐ€ ๋Œ€๊ธฐ์—ด ํ† ํฐ ๋ฐœ๊ธ‰ ์š”์ฒญ
    2. ์œ ์ €๊ฐ€ 1์ดˆ ๊ฐ„๊ฒฉ์œผ๋กœ ํ† ํฐ ์ƒํƒœ ์กฐํšŒ
  • ์ค‘์ 
    • ๋Œ€๊ธฐ์—ด ์‹œ์Šคํ…œ์˜ ์•ˆ์ •์„ฑ ํ™•์ธ
    • ๋‹จ์ˆœ ์กฐํšŒ ์ž‘์—…์—์„œ์˜ ์ตœ๋Œ€ TPS ๋ฐ ํ‰๊ท  RPS ์ธก์ •

 

- ์‹œ๋‚˜๋ฆฌ์˜ค 2 : ์œ ์ € ๋Œ€๊ธฐ์—ด ํ™œ์„ฑ

  • ๋ชฉํ‘œ: ์ฝ˜์„œํŠธ ์˜ˆ์•ฝ ๋ฐ ๊ฒฐ์ œ ๊ณผ์ •์˜ ์ฒ˜๋ฆฌ๋Ÿ‰ ์ธก์ •
  • ํ–‰๋™ ํ๋ฆ„
    1. ์œ ์ €๊ฐ€ ์ฝ˜์„œํŠธ ์ •๋ณด๋ฅผ ์กฐํšŒ
    2. ์œ ์ €๊ฐ€ ํŠน์ • ํšŒ์ฐจ์˜ ์ขŒ์„ ์ •๋ณด๋ฅผ ์กฐํšŒ
    3. ์œ ์ €๊ฐ€ ์ขŒ์„ ์˜ˆ์•ฝ ์š”์ฒญ
    4. ์œ ์ €๊ฐ€ ์˜ˆ์•ฝ ๊ฒฐ์ œ ์š”์ฒญ
  • ์ค‘์ 
    • ๋ณต์žกํ•œ ํŠธ๋žœ์žญ์…˜(์˜ˆ์•ฝ ๋ฐ ๊ฒฐ์ œ) ์ฒ˜๋ฆฌ์—์„œ์˜ ์•ˆ์ •์„ฑ ํ™•์ธ
    • ์—ฌ๋Ÿฌ API ํ˜ธ์ถœ์ด ์—ฐ์†์ ์œผ๋กœ ์ด๋ฃจ์–ด์ง€๋Š” ์‹œ๋‚˜๋ฆฌ์˜ค์˜ TPS/RPS ์ธก์ •
  • ํŠน์ด์‚ฌํ•ญ
    • ํ•˜๋‚˜์˜ ์ฝ˜์„œํŠธ ์Šค์ผ€์ค„์— ๋Œ€ํ•œ ์ขŒ์„์„ 5๋งŒ ๊ฐœ๋กœ ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์‹ค์ œ ์ฝ˜์„œํŠธ๊ฐ€ ๊ฒฝ๊ธฐ์žฅ์—์„œ ์—ด๋ฆด ๋•Œ๋ฅผ ๊ณ ๋ คํ•˜์—ฌ ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

 

 

2. ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ

 

AWS ๋“ฑ ์™ธ๋ถ€ ํด๋ผ์šฐ๋“œ ๋น„์šฉ์„ ์ ˆ์•ฝํ•˜๊ธฐ ์œ„ํ•ด, ๋กœ์ปฌ Docker ํ™˜๊ฒฝ์—์„œ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

- ํ™˜๊ฒฝ ๊ตฌ์„ฑ

  • Docker Compose๋กœ ์‹คํ–‰
    • Spring Boot ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜
    • MySQL
    • Kafka
    • Redis
  • ๋ฆฌ์†Œ์Šค ์ œํ•œ
    • CPU: 0.5 vCPU ~ 2 vCPU
    • ๋ฉ”๋ชจ๋ฆฌ: 512M ~ 4G

 

- ํ…Œ์ŠคํŠธ ๋„๊ตฌ

  • k6
    • ๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ ์Šคํฌ๋ฆฝํŠธ ์ž‘์„ฑ ๋ฐ ์‹คํ–‰
    • ๋ชฉํ‘œ TPS ์„ค์ •๊ณผ SLO ๊ฒ€์ฆ
  • Prometheus + InfluxDB + Grafana
    • Spring Boot Actuator์™€ ์—ฐ๋™ํ•ด ๋ฉ”ํŠธ๋ฆญ ์ˆ˜์ง‘ ๋ฐ ์‹œ๊ฐํ™”
    • k6 ๊ฒฐ๊ณผ์™€ ํ•จ๊ป˜ ์„ฑ๋Šฅ ๋ชจ๋‹ˆํ„ฐ๋ง

 

 

3. ๋ชฉํ‘œ์™€ ๊ฒ€์ฆ ๊ธฐ์ค€

 

- ์‹œ์Šคํ…œ ํ•œ๊ณ„ ์ธก์ •

ํ…Œ์ŠคํŠธ์˜ ์ฃผ์š” ๋ชฉํ‘œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

  1. ์ตœ๋Œ€ TPS: ์‹œ์Šคํ…œ์ด ๋™์‹œ์— ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ์š”์ฒญ์˜ ์ตœ๋Œ€ ๊ฐœ์ˆ˜
  2. ํ‰๊ท  TPS: ์ง€์†์ ์ธ ๋ถ€ํ•˜ ์ƒํ™ฉ์—์„œ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅํ•œ ํ‰๊ท  ์š”์ฒญ ๊ฐœ์ˆ˜
  3. ํ‰๊ท  RPS (Requests Per Second): ์ดˆ๋‹น ์š”์ฒญ ์ฒ˜๋ฆฌ๋Ÿ‰

 

- SLA / SLO ๊ธฐ์ค€

์„œ๋น„์Šค์˜ ํ’ˆ์งˆ ๋ชฉํ‘œ๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค:

  1. SLO
    • p99 ์‘๋‹ต ์‹œ๊ฐ„: 400ms ์ดํ•˜
    • ์„ฑ๊ณต๋ฅ : 99% ์ด์ƒ
  2. SLA
    • ํ‰๊ท  ์‘๋‹ต ์‹œ๊ฐ„: 200ms ์ดํ•˜
    • ์ดˆ๋‹น ์š”์ฒญ ์ฒ˜๋ฆฌ๋Ÿ‰: ์ตœ์†Œ 50 TPS
    • ์ตœ๋Œ€ ๋ถ€ํ•˜ ์กฐ๊ฑด์—์„œ ์„œ๋น„์Šค ์ค‘๋‹จ ๋ฐœ์ƒ๋ฅ : 0%

 

 

 

4. ํ…Œ์ŠคํŠธ ์„ค๊ณ„์™€ ์Šคํฌ๋ฆฝํŠธ

 

- ํ…Œ์ŠคํŠธ ์„ค๊ณ„

๊ฐ ํ…Œ์ŠคํŠธ๋Š” ์‹œ๋‚˜๋ฆฌ์˜ค ๋ณ„ Docker ๋ฆฌ์†Œ์Šค ์ŠคํŽ™(3๊ฐœ)์™€ ํ…Œ์ŠคํŠธ ์ „๋žต(2๊ฐœ)์˜ ์กฐํ•ฉ์œผ๋กœ ์ด 6๊ฐœ๋กœ ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

1. Docker ์ŠคํŽ™

  • 0.5vCPU, 512MB
  • 1vCPU, 1GB
  • 2vCPU, 2GB

2. ํ…Œ์ŠคํŠธ ์ „๋žต

  • VU ์ฆ๊ฐ€ ํ…Œ์ŠคํŠธ - ์ ์ง„์  ์ฆ๊ฐ€๋กœ ์ตœ๋Œ€ ์ฒ˜๋ฆฌ๋Ÿ‰ ํ™•์ธ
export let options = {
    stages: [
        { duration: '10s', target: 10 },  // 10์ดˆ ๋™์•ˆ 10 VU๋กœ ์ฆ๊ฐ€
        { duration: '10s', target: 30 },  // 10์ดˆ ๋™์•ˆ 30 VU๋กœ ์ฆ๊ฐ€
        { duration: '10s', target: 50 },  // 10์ดˆ ๋™์•ˆ 50 VU๋กœ ์ฆ๊ฐ€
        { duration: '10s', target: 100 }, // 10์ดˆ ๋™์•ˆ 100 VU๋กœ ์ฆ๊ฐ€
        { duration: '10s', target: 200 }, // 10์ดˆ ๋™์•ˆ 200 VU๋กœ ์ฆ๊ฐ€
        { duration: '10s', target: 0 },   // 10์ดˆ ๋™์•ˆ 0์œผ๋กœ ๊ฐ์†Œ
    ],
    thresholds: {
        http_req_duration: ['p(99)<400'], // p99๊ฐ€ 400ms ์ดํ•˜
        http_req_failed: ['rate<0.01'],   // ์‹คํŒจ์œจ์ด 1% ์ดํ•˜
    },
};

 

  • ์ŠคํŒŒ์ดํฌ ํ…Œ์ŠคํŠธ - ๊ฐ‘์ž‘์Šค๋Ÿฌ์šด ๋ถ€ํ•˜ ๋ณต์› ๋Šฅ๋ ฅ ํ™•์ธ
export let options = {
    stages: [
        { duration: '10s', target: 100 },  // 10์ดˆ ๋™์•ˆ 100 VU
        { duration: '10s', target: 1000 }, // 10์ดˆ ๋™์•ˆ 1000 VU๋กœ ๊ธ‰์ฆ
        { duration: '30s', target: 100 },  // 30์ดˆ ๋™์•ˆ 100 VU๋กœ ๊ฐ์†Œ
    ],
    thresholds: {
        http_req_duration: ['p(99)<400'], // p99 ์‘๋‹ต ์‹œ๊ฐ„ ์กฐ๊ฑด
        http_req_failed: ['rate<0.05'],   // ์‹คํŒจ์œจ ์กฐ๊ฑด (์ŠคํŒŒ์ดํฌ์—์„œ๋Š” 5% ํ—ˆ์šฉ)
    },
};

 

 

 

- ์‹œ๋‚˜๋ฆฌ์˜ค 1: ์œ ์ € ๋น„ํ™œ์„ฑ

 

์œ ์ € ํ† ํฐ ๋ฐœ๊ธ‰ -> ํ† ํฐ ์ƒํƒœ ์กฐํšŒ (1์ดˆ ๊ฐ„๊ฒฉ์œผ๋กœ 5ํšŒ ๋ฐ˜๋ณต)

export default function () {
    // ํ† ํฐ ๋ฐœ๊ธ‰
    let token = getWaitingToken()
    
    // ํ† ํฐ ์ƒํƒœ ์กฐํšŒ
    for (let i = 0; i < 5; i++) { // 5ํšŒ ๋ฐ˜๋ณต
        getQueueStatus(token)
        sleep(1);
    }
}

 

 

1. 1vCPU, 512MB & VU ์ฆ๊ฐ€ ํ…Œ์ŠคํŠธ

 

 

2. 2vCPU, 1GB & VU ์ฆ๊ฐ€ ํ…Œ์ŠคํŠธ

 

 

3. 2vCPU, 2GB & VU ์ฆ๊ฐ€ ํ…Œ์ŠคํŠธ

 

 

 

5.1vCPU, 512MB & ์ŠคํŒŒ์ดํฌ ํ…Œ์ŠคํŠธ

 

 

5. 2vCPU, 1GB & ์ŠคํŒŒ์ดํฌ ํ…Œ์ŠคํŠธ

 
 
6. 2vCPU, 2GB & ์ŠคํŒŒ์ดํฌ ํ…Œ์ŠคํŠธ
 
 
 
 
 
 
 

- ์‹œ๋‚˜๋ฆฌ์˜ค 2: ์œ ์ € ํ™œ์„ฑ

ํ™œ์„ฑ ํ† ํฐ ๋ฐœ๊ธ‰ -> ์ขŒ์„ ์กฐํšŒ -> ์ขŒ์„ ์˜ˆ์•ฝ -> ๊ฒฐ์ œ

export default function () {
    let token = getActiveToken();

    getConcertSeats(token);
    sleep(2);
    let reservationId = reserveSeat(token);
    sleep(2);
    processPayment(token, reservationId);
    sleep(2);
}
 
 
 
๋ฌธ์ œ ๋ฐœ์ƒ
 
์‹œ๋‚˜๋ฆฌ์˜ค 2์˜ ๊ฒฝ์šฐ, ํ•ด๋‹น ์ฝ˜์„œํŠธ ์Šค์ผ€์ค„์— ๋Œ€ํ•œ ๋ชจ๋“  ์ขŒ์„์„ ์กฐํšŒํ•˜๋Š” ๋กœ์ง์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์‹œ๋‚˜๋ฆฌ์˜ค 1๊ณผ ๋™์ผํ•œ ์กฐ๊ฑด์—์„œ ํ…Œ์ŠคํŠธ ํ•ด๋ณธ ๊ฒฐ๊ณผ ์•„๋ž˜์™€ ๊ฐ™์ด ํž™ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์ด ๋ถ€์กฑํ•˜์—ฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ข…๋ฃŒ๋˜๊ณ  ๋ง์•˜์Šต๋‹ˆ๋‹ค.

 

2024-11-29 00:22:12 2024-11-28T15:22:11.293Z ERROR 1 --- [concert-reservation] [io-8080-exec-32] h.c.i.api.GlobalExceptionHandler         : Exception: [INTERNAL_SERVER_ERROR] CannotCreateTransactionException - An unexpected error occurred..
2024-11-29 00:22:12 
2024-11-29 00:22:12 org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction
2024-11-29 00:22:12     at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:466) ~[spring-orm-6.1.13.jar!/:6.1.13]


...
2024-11-29 00:22:13 Caused by: java.lang.OutOfMemoryError: Java heap space

...

2024-11-29 00:22:13 2024-11-28T15:22:11.296Z ERROR 1 --- [concert-reservation] [io-8080-exec-47] h.c.i.api.GlobalExceptionHandler         : Exception: [INTERNAL_SERVER_ERROR] CannotCreateTransactionException - An unexpected error occurred..
2024-11-29 00:22:13 
2024-11-29 00:22:13 org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction

...

2024-11-29 00:22:13 Caused by: org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection [HikariPool-1 - Connection is not available, request timed out after 20436ms (total=23, active=23, idle=0, waiting=24)] [n/a]

...

2024-11-29 00:23:34 org.springframework.orm.jpa.JpaSystemException: JDBC exception executing SQL [/* <criteria> */ select s1_0.`id`,s1_0.`created_at`,s1_0.`price`,s1_0.`schedule_id`,s1_0.`seat_number`,s1_0.`status`,s1_0.`updated_at`,s1_0.`version` from `seat` s1_0 where s1_0.`schedule_id`=?] [Java heap space] [n/a]
 
์บ์‹œ ์ ์šฉ, Hikari ์ปค๋„ฅ์…˜ ํ’€ ๊ฐœ์ˆ˜ ์ฆ๊ฐ€ ๋“ฑ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ๋ชจ์ƒ‰ํ•ด๋ณด์•˜์ง€๋งŒ ๊ทธ์— ๋”ฐ๋ฅธ ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ๊ฐ€ ์กด์žฌํ•˜์—ฌ ํ•ด๋‹น ์‹œ๋‚˜๋ฆฌ์˜ค๋Š” ์ปจํ…Œ์ด๋„ˆ์˜ ์ž์›์„ 2vCPU, 4GB๋กœ ๊ณ ์ •ํ•˜๊ณ , ์‹œ๋‚˜๋ฆฌ์˜ค๋„ ์•„๋ž˜์™€ ๊ฐ™์ด ๋ณ€๊ฒฝํ•˜์—ฌ ์ง„ํ–‰ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์ถ”ํ›„ ํ•ด๋‹น ๋ฌธ์ œ์— ๋Œ€ํ•ด ๋ถ„์„ํ•ด๋ณผ ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.
 
export let options = {
  stages: [
    { duration: '10s', target: 10 },  // 10์ดˆ ๋™์•ˆ 10 VU๋กœ ์ฆ๊ฐ€
    { duration: '10s', target: 15 },  // 10์ดˆ ๋™์•ˆ 20 VU๋กœ ์ฆ๊ฐ€
    { duration: '10s', target: 20 },  // 10์ดˆ ๋™์•ˆ 30 VU๋กœ ์ฆ๊ฐ€
    { duration: '10s', target: 25 }, // 10์ดˆ ๋™์•ˆ 50 VU๋กœ ์ฆ๊ฐ€
    { duration: '10s', target: 30 }, // 10์ดˆ ๋™์•ˆ 50 VU๋กœ ์ฆ๊ฐ€
    { duration: '10s', target: 0 },   // 10์ดˆ ๋™์•ˆ 0์œผ๋กœ ๊ฐ์†Œ
  ],
  thresholds: {
      http_req_duration: ['p(99)<400'], // p99๊ฐ€ 400ms ์ดํ•˜
      http_req_failed: ['rate<0.01'],   // ์‹คํŒจ์œจ์ด 1% ์ดํ•˜
  },
};
 
 
 
1. 2vCPU, 4GB & VU ์ฆ๊ฐ€ ํ…Œ์ŠคํŠธ
 

 

 

 

 

5. ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ์™€ ๋ถ„์„

 

- Docker ๋ฆฌ์†Œ์Šค ์กฐ์ •๊ณผ ํ…Œ์ŠคํŠธ ์ „๋žต์— ๋”ฐ๋ฅธ ์„ฑ๋Šฅ

Docker ์ŠคํŽ™ ํ…Œ์ŠคํŠธ ์ „๋žต p95 ์‘๋‹ต ์‹œ๊ฐ„(ms) ์ตœ๋Œ€ RPS ์„ฑ๊ณต๋ฅ (%)
1vCPU, 512MB VU ์ฆ๊ฐ€ ํ…Œ์ŠคํŠธ 13.1 239 100%
1vCPU, 512MB ์ŠคํŒŒ์ดํฌ ํ…Œ์ŠคํŠธ 3830 555 100%
2vCPU, 1GB VU ์ฆ๊ฐ€ ํ…Œ์ŠคํŠธ 5.26 239 100%
2vCPU, 1GB ์ŠคํŒŒ์ดํฌ ํ…Œ์ŠคํŠธ 1150 950 100%
2vCPU, 2GB VU ์ฆ๊ฐ€ ํ…Œ์ŠคํŠธ 6.69 240 100%
2vCPU, 2GB ์ŠคํŒŒ์ดํฌ ํ…Œ์ŠคํŠธ 1420 948 100%

 

 

- ๋ถ„์„

1. 1vCPU, 512MB ๋ฆฌ์†Œ์Šค ํ™˜๊ฒฝ

  • VU ์ฆ๊ฐ€ ํ…Œ์ŠคํŠธ
    • p95 ์‘๋‹ต ์‹œ๊ฐ„์€ 13.1ms๋กœ ๋งค์šฐ ์šฐ์ˆ˜ํ•˜๋ฉฐ, SLO ๊ธฐ์ค€(p99 < 400ms) ์ถฉ์กฑ
    • ์ตœ๋Œ€ RPS 239๋กœ ๋™์‹œ ์š”์ฒญ ์ฒ˜๋ฆฌ๋Ÿ‰์€ ์ œํ•œ์ 
    • ์ œํ•œ๋œ ๋ฆฌ์†Œ์Šค ๋‚ด์—์„œ๋Š” CPU์™€ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด ์•ˆ์ •์ 
  • ์ŠคํŒŒ์ดํฌ ํ…Œ์ŠคํŠธ:
    • p95 ์‘๋‹ต ์‹œ๊ฐ„์ด 3830ms๋กœ SLO ๊ธฐ์ค€ ๋ฏธ๋‹ฌ
    • ์ˆœ๊ฐ„ ๋ถ€ํ•˜์—์„œ CPU์™€ ๋ฉ”๋ชจ๋ฆฌ ๋ถ€์กฑ์œผ๋กœ ์ธํ•ด ์ฒ˜๋ฆฌ ์†๋„ ์ €ํ•˜ ๋ฐ ๋ณ‘๋ชฉ ๋ฐœ์ƒ

 

2. 2vCPU, 1GB ๋ฆฌ์†Œ์Šค ํ™˜๊ฒฝ

  • VU ์ฆ๊ฐ€ ํ…Œ์ŠคํŠธ
    • p95 ์‘๋‹ต ์‹œ๊ฐ„์ด 5.26ms๋กœ ๋งค์šฐ ์šฐ์ˆ˜ํ•˜๋ฉฐ, ๋ชจ๋“  SLO/SLA ๊ธฐ์ค€ ์ถฉ์กฑ
    • ์ตœ๋Œ€ RPS 239๋กœ ๋™์‹œ ์š”์ฒญ ์ฒ˜๋ฆฌ๋Ÿ‰์€ ์ œํ•œ๋œ ํ™˜๊ฒฝ๊ณผ ๋™์ผํ•˜์ง€๋งŒ, CPU์™€ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด ์—ฌ์œ ๋กœ์›€
  • ์ŠคํŒŒ์ดํฌ ํ…Œ์ŠคํŠธ
    • p95 ์‘๋‹ต ์‹œ๊ฐ„์ด 1150ms๋กœ SLO ๊ธฐ์ค€ ๋ฏธ๋‹ฌ
    • ์ตœ๋Œ€ RPS 950์œผ๋กœ ์ŠคํŒŒ์ดํฌ ๋ถ€ํ•˜๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์œผ๋‚˜, ์—ฐ๊ฒฐ ๋ณ‘๋ชฉ์ด ๋ฐœ์ƒ
    • ๋™์‹œ ์š”์ฒญ ์ฒ˜๋ฆฌ๋Ÿ‰ ์ฆ๊ฐ€ ์‹œ I/O ๋ณ‘๋ชฉ์œผ๋กœ ์ธํ•ด ์‘๋‹ต ์†๋„๊ฐ€ ๋А๋ ค์ง

3. 2vCPU, 2GB ๋ฆฌ์†Œ์Šค ํ™˜๊ฒฝ

  • VU ์ฆ๊ฐ€ ํ…Œ์ŠคํŠธ
    • p95 ์‘๋‹ต ์‹œ๊ฐ„์ด 6.69ms๋กœ ๋งค์šฐ ์šฐ์ˆ˜ํ•˜๋ฉฐ, ๋ชจ๋“  SLO/SLA ๊ธฐ์ค€ ์ถฉ์กฑ
    • ์ตœ๋Œ€ RPS 240์œผ๋กœ ๋™์‹œ ์š”์ฒญ ์ฒ˜๋ฆฌ๋Ÿ‰์ด ์•ˆ์ •์ 
    • ๋ถ€ํ•˜ ๋ถ„์‚ฐ์ด ์ž˜ ์ด๋ฃจ์–ด์กŒ์œผ๋ฉฐ, ๋ณ‘๋ชฉ ์—†์ด ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ
  • ์ŠคํŒŒ์ดํฌ ํ…Œ์ŠคํŠธ
    • p95 ์‘๋‹ต ์‹œ๊ฐ„์ด 1420ms๋กœ SLO ๊ธฐ์ค€ ๋ฏธ๋‹ฌ
    • ์ตœ๋Œ€ RPS 948๋กœ ๋†’์€ ํŠธ๋ž˜ํ”ฝ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์œผ๋‚˜, ์ˆœ๊ฐ„์ ์ธ ์š”์ฒญ ํญ์ฃผ์—์„œ ์ง€์—ฐ ๋ฐœ์ƒ
    • I/O ์ฒ˜๋ฆฌ ๋ณ‘๋ชฉ์œผ๋กœ ์ธํ•œ ์ง€์—ฐ ๊ฐ€๋Šฅ์„ฑ

4. ์‹œ๋‚˜๋ฆฌ์˜ค 2 ๋ฏธํ•ด๊ฒฐ ๋ฌธ์ œ

  • ๋†’์€ ์ŠคํŒŒ์ดํฌ ํŠธ๋ž˜ํ”ฝ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์žˆ์–ด ๋ชจ๋“  ํ™˜๊ฒฝ์—์„œ Redis๋‚˜ DB ์—ฐ๊ฒฐ ๋ณ‘๋ชฉ์ด ๋ฐœ์ƒ ๊ฐ€๋Šฅ
  • Redis ์ปค๋„ฅ์…˜ ํ’€ ๋ถ€์กฑ ๋˜๋Š” DB์˜ ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ ํ•œ๊ณ„๊ฐ€ ๋ณ‘๋ชฉ์˜ ์ฃผ์š” ์›์ธ์ผ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Œ
  • ์ œํ•œ๋œ CPU/๋ฉ”๋ชจ๋ฆฌ์—์„œ ์ŠคํŒŒ์ดํฌ ํŠธ๋ž˜ํ”ฝ ์‹œ ๋ณ‘๋ชฉ ํ˜„์ƒ์ด ์‹ฌํ™”๋จ

 

 

 

6. ๊ฒฐ๋ก 

 

  • ์‹œ์Šคํ…œ ํ•œ๊ณ„ ์ธก์ •
    • ์ œํ•œ๋œ ๋ฆฌ์†Œ์Šค ํ™˜๊ฒฝ์—์„œ๋Š” CPU์™€ ๋ฉ”๋ชจ๋ฆฌ ๋ถ€์กฑ์ด ์„ฑ๋Šฅ ๋ณ‘๋ชฉ์˜ ์ฃผ์š” ์›์ธ
    • DB ์ปค๋„ฅ์…˜ ํ’€ ํฌ๊ธฐ ์ฆ๊ฐ€ ๋ฐ ์ฟผ๋ฆฌ ์ตœ์ ํ™” ํ•„์š”
  • SLA/SLO ๊ฒ€์ฆ
    • 2vCPU, 2GB ํ™˜๊ฒฝ์—์„œ ์ตœ๋Œ€ TPS 948๊ณผ ํ‰๊ท  ์‘๋‹ต ์‹œ๊ฐ„ 200ms ์ดํ•˜๋กœ SLO ๊ธฐ์ค€ ์ถฉ์กฑ
    • VU ์ฆ๊ฐ€ ํ…Œ์ŠคํŠธ์—์„œ๋Š” SLO ๊ธฐ์ค€์„ ๋ชจ๋‘ ์ถฉ์กฑํ–ˆ์œผ๋‚˜, ์ŠคํŒŒ์ดํฌ ๋ถ€ํ•˜์—์„œ๋Š” ๋ชจ๋‘ ์„ฑ๋Šฅ ๋ณ‘๋ชฉ์ด ๋ฐœ์ƒ
  • ํ–ฅํ›„ ๊ณ„ํš
    • AWS ํ™˜๊ฒฝ์—์„œ ์‹ค์ œ ๋ฐฐํฌ๋ฅผ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ํ•˜์—ฌ ๋” ๋†’์€ ํŠธ๋ž˜ํ”ฝ ์ฒ˜๋ฆฌ ์„ฑ๋Šฅ์„ ๊ฒ€์ฆ
    • ์บ์‹ฑ, ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ตœ์ ํ™” ๋“ฑ์œผ๋กœ ์„ฑ๋Šฅ์„ ์ถ”๊ฐ€ ๊ฐœ์„ 

 

 

๋งˆ์น˜๋ฉฐ

์ด๋ฒˆ ํ…Œ์ŠคํŠธ๋ฅผ ํ†ตํ•ด Docker ํ™˜๊ฒฝ์—์„œ ์ž์› ์กฐ์ ˆ๊ณผ ๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ ์กฐํ•ฉ์œผ๋กœ ์‹œ์Šคํ…œ์˜ ์•ˆ์ •์„ฑ๊ณผ ์„ฑ๋Šฅ ํ•œ๊ณ„๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์‹ค์ œ ์šด์˜ ํ™˜๊ฒฝ์—์„œ๋„ ์„ฑ๋Šฅ์„ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•ด ์–ด๋–ค ์ ์„ ๊ณ ๋ คํ•ด์•ผ ํ•  ์ง€ ์ƒ๊ฐํ•ด ๋ณผ ์ˆ˜ ์žˆ๋Š” ์‹œ๊ฐ„์ด์—ˆ์Šต๋‹ˆ๋‹ค.

๊ธฐ๋ณธ ํ•จ์ˆ˜ ๋‚ด๋ณด๋‚ด๊ธฐ() { let token = getActiveToken(); getConcertSchedules(ํ† ํฐ); ์ˆ˜๋ฉด(1); getConcertSeats(ํ† ํฐ); ์ˆ˜๋ฉด(1); bookingId = ReserveSeat(token); ์ˆ˜๋ฉด(2); processPayment(ํ† ํฐ, ์˜ˆ์•ฝ ID); ์ˆ˜๋ฉด(2); }