본문 바로가기
토이프로젝트/선착순쿠폰발급

[선착순 쿠폰 발급 4편] 동시 요청 테스트

by 무대포 개발자 2023. 3. 27.
728x90
반응형

source 는 Github 에 있습니다.

목차는 선착순 쿠폰 발급 에 있습니다.

[선착순 쿠폰 발급 4편] 동시 요청 테스트

코틀린, Redis 공부를 위해 작성했습니다.

동시 요청 테스트

  • 동시 요청을 하여 쿠폰 발급이 제대로 처리돼는지 확인할려고 테스트를 진행했습니다.
  • 사용한 테스트 툴은 K6 을 사용했으며, 해당 툴을 사용한 이유는 코드로 테스트 시나리오를 만들기가 편하기 때문입니다.
    • 다른 툴들을 사용해봤는데 테스트 시나리오가 조금 복잡해지면 사용하기 어렵다는 점이 있었습니다.

Redis 더미 데이터 생성

실행 방법

  • 앞에서 쿠폰을 미리 발급하고 쿠폰 발급 요청을 진행해야하니 Redis 에 미리 더미 데이터를 만드는 프로그램을 만들었습니다.

  • redis jedis 를 사용했습니다.

  • main 을 실행시키면 되며, 실행하기 전에 redis 가 떠있어야 합니다. (localhost, 6379)

    • docker-compose 를 만들어놨으니 docker-compose 를 실행시키면 됩니다.
docker-compose -f ./docker-compose-redis.yml up -d
fun main(args: Array<String>) {
    CreateDummyDataTest().createDummyData()
}

class CreateDummyDataTest {
    fun createDummyData() {
        // Redis 접속 정보
        val host = "localhost"
        val port = 6379

        // Jedis 클라이언트 생성
        val jedis = Jedis(host, port)

        // 샘플 데이터 추가
        for (i in 1..1000) {
            jedis.sadd("available-coupon", "coupon$i")
        }

        // 종료
        jedis.close()
    }
}

데이터 생성 확인

  • 더미 데이터를 추가하고 redis cli 들어가서 데이터가 제대로 생성됐는지 확인합니다.
docker exec -it redis_main redis-cli

SCARD available-coupon

redis_dummy_create_result

K6 동시 요청

source

// k6 run coupon-issuance-performance.js
// k6 스크립트 실행하기 전에 WAS Application 기동시켜놔야함 (core-api/CoreApiApplication.kt)

import http from 'k6/http';
import { check } from 'k6';

export let options = {
  vus: 5, // vus 옵션은 가상 사용자 (Virtual User, VU)
    duration: "10s" // duration 옵션은 테스트를 실행할 총 시간. 여기서는 10초
};

export default function () {
    var url = "http://localhost:8080/api/v1/coupon/issuance/request";
    const payload = { data: `user${Math.round(Math.random() * 100000)}` };
    const params = {
      headers: {
        'Content-Type': 'application/json',
      },
    };
    const res = http.post(url, JSON.stringify(payload), params);
    check(res, { 'status is 200': (r) => r.status === 200 });
}
  • 위 소스를 설명하면 5명의 가상 사용자가 10초동안 쿠폰 발급 요청 API 를 호출합니다.
    • 해당 API 가 하는 역할은 사용자의 userId 를 받아서 coupon id 와 맵핑을 시켜주는 역할을 합니다.
  • 마지막에 응답 값이 200 으로 왔는지 체크합니다.

실행 방법

  • 실행 하기 전에, k6 이 설치돼있어야 합니다.
k6 run coupon-issuance-performance.js

K6 실행 결과

  execution: local
     script: coupon-issuance-performance.js
     output: -

  scenarios: (100.00%) 1 scenario, 5 max VUs, 40s max duration (incl. graceful stop):
           * default: 5 looping VUs for 10s (gracefulStop: 30s)


     ✓ status is 200

     checks.........................: 100.00% ✓ 36656      ✗ 0    
     data_received..................: 6.7 MB  668 kB/s
     data_sent......................: 6.7 MB  670 kB/s
     http_req_blocked...............: avg=4.16µs  min=0s      med=1µs    max=5.6ms    p(90)=2µs    p(95)=3µs   
     http_req_connecting............: avg=2.08µs  min=0s      med=0s     max=3.52ms   p(90)=0s     p(95)=0s    
     http_req_duration..............: avg=1.29ms  min=488µs   med=1.03ms max=383.21ms p(90)=2.08ms p(95)=2.5ms 
       { expected_response:true }...: avg=1.29ms  min=488µs   med=1.03ms max=383.21ms p(90)=2.08ms p(95)=2.5ms 
     http_req_failed................: 0.00%   ✓ 0          ✗ 36656
     http_req_receiving.............: avg=23.73µs min=6µs     med=14µs   max=3.51ms   p(90)=48µs   p(95)=66µs  
     http_req_sending...............: avg=6.6µs   min=3µs     med=5µs    max=2.93ms   p(90)=9µs    p(95)=14µs  
     http_req_tls_handshaking.......: avg=0s      min=0s      med=0s     max=0s       p(90)=0s     p(95)=0s    
     http_req_waiting...............: avg=1.26ms  min=471µs   med=1ms    max=377.95ms p(90)=2.04ms p(95)=2.45ms
     http_reqs......................: 36656   3665.06087/s
     iteration_duration.............: avg=1.36ms  min=526.2µs med=1.08ms max=392.76ms p(90)=2.15ms p(95)=2.6ms 
     iterations.....................: 36656   3665.06087/s
     vus............................: 5       min=5        max=5  
     vus_max........................: 5       min=5        max=5  


running (10.0s), 0/5 VUs, 36656 complete and 0 interrupted iterations
default ✓ [======================================] 5 VUs  10s
  • 요약하면 10초동안 5명의 사용자가 36656 명의 요청을 수행했고 전부 200 으로 응답이 왔습니다.

Redis 결과

  • 위에서 쿠폰을 미리 1000개를 만들어놨으니 userId 와 couponId 맵핑이 1000개 만들어져있어야 합니다.
  • userId 와 couponId 맵핑을 담당하는 Redis key 는 coupon-user-mapping 입니다.

mapping_result

댓글