서버 성능 테스트를 해야하는 업무가 발생하여 어떤식으로 진행했는지 공유 해보려고 합니다.
하루 기준 약 300만의 유저가 1~2일 동안 저희 서비스에 유입이될 수 있는 상황이였습니다.

이에 따라 3000000 / 24 / 60 / 60 1초에 약 34명이 유입될 수 있다고 단순하게 계산을 한 후

서버 성능 테스트를 진행해보기로 했습니다.

상황에 따라 어느 언어나 툴을 사용하던 시나리오를 잘 구성하여 체크하면 된다고하여

가장 효율적인 방법을 고민하게 되었고,

가장 자신 있는 C# Conole 프로젝트로 진행 해보려고 합니다.

시나리오

필수 요소인 회원가입 & 로그인 작업 이후 유저가 실제로 행동할 Task를 분석하여

시나리오를 구성해보았습니다.

 

1초에 30명 ~ 50명 유저가 유입된다.
모든 유저는 각 Task 당 약 1초의 delay로 진행된다.
A (로그인) -> B Task -> C Task -> D Task -> B Task -> C Task -> D Task -> Exit

 

성능 테스트용 봇 개발

.NET Console 프로젝트를 활용하여 개발 하였습니다.

using log4net;
using log4net.Config;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Linq;

class PerformanceTestBot
{
    private static readonly ILog log = LogManager.GetLogger(typeof(PerformanceTestBot));
    private static readonly HttpClient client = new HttpClient();
    private const int userCountPerSecond = 30; // 초당 생성할 유저 수
    private static bool keepRunning = true;
    private static int userCounter = 1; // 생성 시작할 유저 id

    static async Task Main(string[] args)
    {
        // Log4net 초기화
        XmlConfigurator.Configure(new FileInfo("log4net.config"));
        log.Info("Starting performance test...");

        Console.CancelKeyPress += (sender, e) =>
        {
            e.Cancel = true;
            keepRunning = false;
            log.Info("Stopping user creation...");
        };

        await StartUserCreationLoop(userCountPerSecond);
        log.Info("Performance test completed.");
    }

    // 유저 생성 루프
    private static async Task StartUserCreationLoop(int userCountPerSecond)
    {
        while (keepRunning)
        {
            var tasks = new List<Task>();

            for (int j = 0; j < userCountPerSecond; j++)
            {
                tasks.Add(CreateAndRunScenario());
            }

            _ = Task.WhenAll(tasks);
            await Task.Delay(10000); //1초
        }
    }

    // 유저 생성 후 시나리오 실행
    private static async Task CreateAndRunScenario()
    {
        int userId = Interlocked.Increment(ref userCounter);

        // SSL 인증서 무시 설정을 추가한 HttpClient 생성
        var handler = new HttpClientHandler
        {
            ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true
        };

        using (var localClient = new HttpClient(handler))
        {
            var loginToken = await ATask();

            if (!string.IsNullOrEmpty(loginToken))
            {
                log.Info($"[A Task] User {userId} signed up successfully with login token: {loginToken}");

                for (int i = 0; i < 3; i++)
                {
                    await BTask();
                    log.Info($"[B Task] User {userId} with token {loginToken} called API B.");

                    await Task.Delay(2000);

                    await CTask();
                    log.Info($"[C Task] User {userId} with token {loginToken} called API C");

                    await Task.Delay(2000);

                    await DTask();
                    log.Info($"[D Task] User {userId} with token {loginToken} called API D");

                    await Task.Delay(2000);
                }

                log.Info($"User {userId} has completed all missions and is exiting.");
            }
            else
            {
                log.Warn($"[A Task] User {userId} failed to sign up.");
            }
        }
    }


    #region API methods

    // A Task
    private static async Task<string> ATask()
    {
        // A API 호출
    }

    // B Task
    public static async Task BTask()
    {
        // B API 호출
    }

    // C Task
    public static async Task CTask()
    {
        // C API 호출
    }

    // D Task
    public static async Task DTask()
    {
        // D API 호출
    }

    #endregion
}

 

성능 테스트 과정

서버 모니터링 시스템을 킨 후 현재 CPU, Memory를 확인한 후 프로그램을 실행하였습니다.
초당 30명 생성은 약 5초 후에 CPU 100% 차면서 서버가 멈췄습니다😂
현재 개발 서버 스펙은 초당 15명 생성이 한계였습니다😂


개발 서버를 2배로 스펙업 후 초당 40명 생성을 확인 하였고

약 3시간 동작 결과 CPU 70%로 안정적으로 시나리오 동작 하는 것을 확인 하였습니다.

 

성능 테스트 완료

상용 서버와 개발 서버 스펙업을 비교 하고 유저 유입 기간에 맞춰서

상용 서버 스펙업을 진행하기로 하였습니다.


그리고 성공적으로 상용서버에서 유저 유입에 성공 하였습니다🎈 🎈 🎈

웹 취약점 검사를 위해 OWASP ZAP – Download (zaproxy.org)를 설치를 진행하던 중 해당 오류가 발생 하였습니다.

Java Downloads | Oracle jdk 설치 후 해당 .exe 파일을 연결해주니 해당 오류가 사라졌습니다.

 

오류 화면

 

여러가지 프로젝트를 동시에 진행할 경우 node.js 호환 에러로

애를 먹었던 경우가 많아 노드 버전 관리를 할 수 있는 n , nvm에 대해 알아보겠습니다.

 

linux에서는 노드 버전을 관리하기 위해 n을 사용합니다.

그러나 windows에서는 지원을 하지 않기 때문에

같은 기능을 하는 nvm을 설치 해보고 사용해보려고 합니다.

 

nvm(Node Version Manager)이란 ?

협업을 할 때, 또는 다양한 프로젝트를 동시에 진행해야 할 때

각 프로젝트 별로 node.js 호환을 위해 사용하는 node 버전 관리 도구 입니다.

 

1. install

https://github.com/coreybutler/nvm-windows/releases

 

Releases · coreybutler/nvm-windows

A node.js version management utility for Windows. Ironically written in Go. - coreybutler/nvm-windows

github.com

2. nvm 사용법

# node list
nvm ls

# node version install
nvm install 17.5.0

# nvm에서 특정 버전 node 활성화 하기
nvm use 17.5.0

# nvm에서 특정 버전 node 삭제
nvm uninstall 17.5.0

# nvm에서 어떤 node 사용할지 default 설정
nvm alias default v12.18.2

 

 

 

windows에서 docker를 설치하기 위해서 여러가지 방법이 있습니다.

그 중 가장 간단한 docker hub 설치하는 법을 정리해보도록 하겠습니다.

 

1. docker hub 설치

https://www.docker.com/products/docker-desktop/

 

Download Docker Desktop | Docker

Docker Desktop is available to download for free on Mac, Windows, or Linux operating systems. Get started with Docker today!

www.docker.com

 

2. wsl2 installation is incomplete 오류 해결

https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi

설치 후 재부팅 하면 해결이 됩니다.

 

3. 실행 확인

 

* WSL(Windows Subsystem for Linux)란?

- Windows 운영체제에서  Linux 실행파일들을 함께 사용할 수 있도록 호환성을 추가하는 아키텍처라 할 수 있다.

'Server > Docker' 카테고리의 다른 글

[Ubuntu] Docker 설치하기  (0) 2023.10.23
[Centos] aws linux centos에 docker로 jenkins 띄우기  (0) 2023.08.08
.net core React docker image 만드는 법  (0) 2023.04.03
Docker 명령어  (0) 2023.01.29
Docker 설치 - linux편  (0) 2023.01.29

+ Recent posts