[프로젝트] 동시성 테스트를 해봤다 - 1

Godtaek·2024년 2월 12일
0

project

목록 보기
2/4

1. 들어가기 앞서

이번 테스트는 rough한 로직을 그대로 테스트해 볼 예정이다.

  • 주문 API를 테스트할 거고, 요청이 한 번 올 때마다, stock을 하나씩 줄일 예정이다.
  • 동시성 이슈 때문에 숫자가 맞춰지지 않을 거라 예상된다.
  • Redis를 도입하기 전보다 느릴 거고, db lock 거는 거보단 빠를 것이다.

2. Python 테스트 코드

item/{userId}/{itemId}로 요청해서 item의 stock을 1씩 줄이는 테스트

  • 10000개의 user가 한 번씩 요청한다.
  • 10개의 상품 중 랜덤하게 하나를 골라 요청한다.
  • 코드는 copilot과 검색을 이용했다.
  • requests만 pip install하면 된다.
import requests
import random
from concurrent.futures import ThreadPoolExecutor
import time


def send_http_request(url, userId, itemId):
    global my_dict, error
    try:
        response = requests.put(f"{url}/{userId}/{itemId}")
        # 요청이 성공했다면, item_id에 하나를 추가해서 item 횟수를 카운트한다.
        if response.status_code == 200:
            my_dict[itemId] += 1
        else:
            error += 1
    except Exception as e:
        print(f"Error sending request to {url} with userId {userId} and itemId {itemId}: {e}")


def main():
    global my_dict, error
    # 10000번 요청 보낼 예정이다.
    num_requests = 10000
    # item 별 몇 번이 왔는지 확인할 예정
    my_dict = {i: 0 for i in range(1,11)}
    # 기본 api url을 넣어주면 된다.
    base_url = {url}
	
    # 시간을 재기 위한 start_time
    start_time = time.time()
    # 에러 숫자를 센다.
    error = 0
    # 동시에 Thread 작업을 할 예정이다.
    with ThreadPoolExecutor(max_workers=num_requests) as executor:
        # 작업 목록을 작성한다. 
        tasks = [executor.submit(send_http_request, base_url, userId, random.randint(1, 10)) for userId in
                 range(1, num_requests + 1)]

        # 모든 작업이 완료될 때까지 기다린다.
        for future in tasks:
            future.result()

    # 타이머 종료
    end_time = time.time()

    # 걸린 시간 계산
    elapsed_time = end_time - start_time
    print(f"Elapsed time: {elapsed_time} seconds")
    print(f"item used: {my_dict}")
    print(f"error: {error}")


if __name__ == "__main__":
    main()

3. 결과

평균 시간 : 27~30초
에러 수 : 그때 그때 달랐으나, 로직의 에러는 나지 않았고 총 쓰레드 수의 에러가 존재했다.
API로 호출한 재고 수: item used: {1: 984, 2: 1035, 3: 984, 4: 979, 5: 994, 6: 1012, 7: 967, 8: 1038, 9: 1048, 10: 959}

실제 재고

생각보다 재고 수가 크게 차이났다.

Synchronized 키워드와 낙관적인 락, 비관적인 락 그리고 Redis를 추가로 더 실험해 볼 예정이다.

profile
성장하는 개발자가 되겠습니다

0개의 댓글