258 lines
9.1 KiB
C#
258 lines
9.1 KiB
C#
using ClientTester.DummyService;
|
|
using ClientTester.EchoDummyService;
|
|
using ClientTester.StressTest;
|
|
using ClientTester.Utils;
|
|
using Serilog;
|
|
|
|
class EcoClientTester
|
|
{
|
|
public static string SERVER_IP = "localhost";
|
|
public static int SERVER_PORT = 9500;
|
|
public static readonly string CONNECTION_KEY = "test";
|
|
public static int CLIENT_COUNT = 100;
|
|
|
|
private async Task StartEchoDummyTest()
|
|
{
|
|
try
|
|
{
|
|
CancellationTokenSource cts = new CancellationTokenSource();
|
|
Console.CancelKeyPress += (_, e) =>
|
|
{
|
|
e.Cancel = true;
|
|
Log.Warning("[SHUTDOWN] Ctrl+C 감지, 종료 중...");
|
|
cts.Cancel();
|
|
};
|
|
|
|
EchoDummyClientService service =
|
|
new EchoDummyClientService(CLIENT_COUNT, SERVER_IP, SERVER_PORT, CONNECTION_KEY, 100);
|
|
service.OnAllDisconnected += () =>
|
|
{
|
|
Log.Warning("[SHUTDOWN] 종료 이벤트 발생, 종료 중...");
|
|
cts.Cancel();
|
|
};
|
|
|
|
// service.IsTest = true;
|
|
// service.TestCount = 100;
|
|
await service.RunAsync(cts.Token);
|
|
|
|
service.PrintStats();
|
|
service.Stop();
|
|
|
|
await Log.CloseAndFlushAsync();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.Error($"[SHUTDOWN] 예외 발생 : {e}");
|
|
}
|
|
}
|
|
|
|
private async Task StartDummyTest()
|
|
{
|
|
try
|
|
{
|
|
CancellationTokenSource cts = new CancellationTokenSource();
|
|
Console.CancelKeyPress += (_, e) =>
|
|
{
|
|
e.Cancel = true;
|
|
Log.Warning("[SHUTDOWN] Ctrl+C 감지, 종료 중...");
|
|
cts.Cancel();
|
|
};
|
|
|
|
DummyClientService service =
|
|
new DummyClientService(CLIENT_COUNT, SERVER_IP, SERVER_PORT, CONNECTION_KEY, 100);
|
|
service.OnAllDisconnected += () =>
|
|
{
|
|
Log.Warning("[SHUTDOWN] 종료 이벤트 발생, 종료 중...");
|
|
cts.Cancel();
|
|
};
|
|
|
|
await service.RunAsync(cts.Token);
|
|
|
|
service.PrintStats();
|
|
service.Stop();
|
|
|
|
await Log.CloseAndFlushAsync();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.Error($"[SHUTDOWN] 예외 발생 : {e}");
|
|
}
|
|
}
|
|
|
|
private async Task StartStressTest(int duration, int sendInterval, int rampInterval, int clientsPerRamp)
|
|
{
|
|
try
|
|
{
|
|
CancellationTokenSource cts = new CancellationTokenSource();
|
|
Console.CancelKeyPress += (_, e) =>
|
|
{
|
|
e.Cancel = true;
|
|
Log.Warning("[SHUTDOWN] Ctrl+C 감지, 종료 중...");
|
|
cts.Cancel();
|
|
};
|
|
|
|
StressTestService service = new StressTestService(
|
|
CLIENT_COUNT, SERVER_IP, SERVER_PORT, CONNECTION_KEY,
|
|
durationSec: duration,
|
|
sendIntervalMs: sendInterval,
|
|
rampUpIntervalMs: rampInterval,
|
|
clientsPerRamp: clientsPerRamp);
|
|
|
|
service.OnTestCompleted += () =>
|
|
{
|
|
Log.Information("[STRESS] 테스트 시간 종료.");
|
|
};
|
|
|
|
try
|
|
{
|
|
await service.RunAsync(cts.Token);
|
|
}
|
|
catch (OperationCanceledException) { }
|
|
|
|
service.PrintFinalReport();
|
|
|
|
string timestamp = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss");
|
|
string csvPath = $"results/stress_{CLIENT_COUNT}clients_{timestamp}.csv";
|
|
Directory.CreateDirectory("results");
|
|
service.ExportCsv(csvPath);
|
|
|
|
service.Stop();
|
|
await Log.CloseAndFlushAsync();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.Error($"[SHUTDOWN] 예외 발생 : {e}");
|
|
}
|
|
}
|
|
|
|
private static void PrintUsage()
|
|
{
|
|
Console.WriteLine();
|
|
Console.WriteLine("사용법:");
|
|
Console.WriteLine(" EchoClientTester 대화형 모드");
|
|
Console.WriteLine(" EchoClientTester stress [옵션] 스트레스 테스트");
|
|
Console.WriteLine();
|
|
Console.WriteLine("스트레스 테스트 옵션:");
|
|
Console.WriteLine(" -c, --clients <수> 클라이언트 수 (기본: 50)");
|
|
Console.WriteLine(" -d, --duration <초> 테스트 시간 (기본: 60, 0=무제한)");
|
|
Console.WriteLine(" -i, --interval <ms> 전송 주기 (기본: 100)");
|
|
Console.WriteLine(" -r, --ramp <ms> Ramp-up 간격 (기본: 1000)");
|
|
Console.WriteLine(" -b, --batch <수> Ramp-up 당 클라이언트 수 (기본: 10)");
|
|
Console.WriteLine(" --ip <주소> 서버 IP (기본: localhost)");
|
|
Console.WriteLine(" --port <포트> 서버 포트 (기본: 9500)");
|
|
Console.WriteLine();
|
|
Console.WriteLine("예시:");
|
|
Console.WriteLine(" EchoClientTester stress -c 100 -d 120");
|
|
Console.WriteLine(" EchoClientTester stress -c 200 -d 60 -r 500 -b 20 --ip 192.168.0.10");
|
|
}
|
|
|
|
private static async Task Main(string[] args)
|
|
{
|
|
// 유니코드 문자(═, ║ 등) 콘솔 깨짐 방지
|
|
Console.OutputEncoding = System.Text.Encoding.UTF8;
|
|
|
|
// 크래시 덤프 핸들러 (Release: .log + .dmp / Debug: .log)
|
|
CrashDumpHandler.Register();
|
|
|
|
// .MinimumLevel.Warning() // Warning 이상만 출력 배포시
|
|
string timestamp = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss");
|
|
|
|
Log.Logger = new LoggerConfiguration()
|
|
.MinimumLevel.Debug()
|
|
.WriteTo.Console()
|
|
.WriteTo.File($"logs2/log_{timestamp}.txt")
|
|
.CreateLogger();
|
|
|
|
EcoClientTester tester = new EcoClientTester();
|
|
|
|
// CLI 모드: stress 명령
|
|
if (args.Length > 0 && args[0].Equals("stress", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
// 기본값
|
|
CLIENT_COUNT = 50;
|
|
int duration = 60;
|
|
int sendInterval = 100;
|
|
int rampInterval = 1000;
|
|
int clientsPerRamp = 10;
|
|
|
|
for (int i = 1; i < args.Length; i++)
|
|
{
|
|
switch (args[i])
|
|
{
|
|
case "-c": case "--clients":
|
|
if (i + 1 < args.Length) CLIENT_COUNT = int.Parse(args[++i]);
|
|
break;
|
|
case "-d": case "--duration":
|
|
if (i + 1 < args.Length) duration = int.Parse(args[++i]);
|
|
break;
|
|
case "-i": case "--interval":
|
|
if (i + 1 < args.Length) sendInterval = int.Parse(args[++i]);
|
|
break;
|
|
case "-r": case "--ramp":
|
|
if (i + 1 < args.Length) rampInterval = int.Parse(args[++i]);
|
|
break;
|
|
case "-b": case "--batch":
|
|
if (i + 1 < args.Length) clientsPerRamp = int.Parse(args[++i]);
|
|
break;
|
|
case "--ip":
|
|
if (i + 1 < args.Length) SERVER_IP = args[++i];
|
|
break;
|
|
case "--port":
|
|
if (i + 1 < args.Length) SERVER_PORT = int.Parse(args[++i]);
|
|
break;
|
|
case "-h": case "--help":
|
|
PrintUsage();
|
|
return;
|
|
}
|
|
}
|
|
|
|
await tester.StartStressTest(duration, sendInterval, rampInterval, clientsPerRamp);
|
|
return;
|
|
}
|
|
|
|
// CLI 모드: help
|
|
if (args.Length > 0 && (args[0] == "-h" || args[0] == "--help"))
|
|
{
|
|
PrintUsage();
|
|
return;
|
|
}
|
|
|
|
// 대화형 모드 (기존)
|
|
Log.Information("========== 더미 클라 테스터 ==========");
|
|
Log.Information("1. 에코 서버");
|
|
Log.Information("2. 더미 클라(이동만)");
|
|
Log.Information("3. 스트레스 테스트 (부하)");
|
|
Log.Information("====================================");
|
|
Log.Information("1 / 2 / 3 : ");
|
|
|
|
string? input = Console.ReadLine();
|
|
if (!int.TryParse(input, out int choice) || choice < 1 || choice > 3)
|
|
{
|
|
Log.Warning("1, 2, 3 중 입력하세요.");
|
|
return;
|
|
}
|
|
|
|
if (choice == 1)
|
|
{
|
|
await tester.StartEchoDummyTest();
|
|
}
|
|
else if (choice == 2)
|
|
{
|
|
await tester.StartDummyTest();
|
|
}
|
|
else if (choice == 3)
|
|
{
|
|
// 대화형 스트레스 테스트 설정
|
|
Log.Information("클라이언트 수 (기본 50): ");
|
|
string? countInput = Console.ReadLine();
|
|
CLIENT_COUNT = string.IsNullOrEmpty(countInput) ? 50 : int.Parse(countInput);
|
|
|
|
Log.Information("테스트 시간(초) (기본 60, 0=무제한): ");
|
|
string? durInput = Console.ReadLine();
|
|
int dur = string.IsNullOrEmpty(durInput) ? 60 : int.Parse(durInput);
|
|
|
|
await tester.StartStressTest(dur, 100, 1000, 10);
|
|
}
|
|
}
|
|
}
|