이번 테스트는 rough한 로직을 그대로 테스트해 볼 예정이다.
item/{userId}/{itemId}로 요청해서 item의 stock을 1씩 줄이는 테스트
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()
평균 시간 : 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를 추가로 더 실험해 볼 예정이다.