Files
a301_mmo_game_server/ClientTester/README.md

305 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ClientTester - MMO 서버 테스트 도구
MMO Game Server의 네트워크 성능 검증 및 부하 테스트를 위한 클라이언트 시뮬레이터.
---
## 1. 환경 (라이브러리)
| 항목 | 버전 | 용도 |
|------|------|------|
| .NET | 9.0 | 런타임 |
| LiteNetLib | 2.0.2 | UDP 네트워크 통신 (서버와 동일) |
| protobuf-net | 3.2.56 | 패킷 직렬화/역직렬화 |
| Serilog | 4.3.1 | 구조적 로깅 |
| Serilog.Sinks.Console | 6.0.0 | 콘솔 출력 |
| Serilog.Sinks.File | 7.0.0 | 파일 로깅 |
| Microsoft.Diagnostics.NETCore.Client | 0.2.553101 | 크래시 힙 덤프 (Release만) |
### 빌드
```bash
cd ClientTester/EchoClientTester
dotnet build
```
---
## 2. 디렉토리 구조
```
ClientTester/
├── EchoClientTester/
│ ├── Program.cs # 진입점 (대화형 + CLI)
│ ├── EchoClientTester.csproj
│ ├── Vector3.cs # 위치 구조체
│ │
│ ├── DummyService/ # 이동 테스트
│ │ ├── DummyClientService.cs # 다중 더미 클라 관리
│ │ ├── DummyClients.cs # 개별 더미 클라 (이동 시뮬)
│ │ └── MapBounds.cs # 맵 경계 / 벽 충돌
│ │
│ ├── EchoDummyService/ # Echo RTT 테스트
│ │ ├── EchoDummyClientService.cs # 다중 에코 클라 관리
│ │ └── EchoDummyClients.cs # 개별 에코 클라 (RTT 측정)
│ │
│ ├── StressTest/ # 부하/스트레스 테스트
│ │ ├── StressTestService.cs # 오케스트레이터 (Ramp-up, 통계, CSV)
│ │ └── StressTestClient.cs # 통합 클라 (이동 + Echo 동시)
│ │
│ ├── Packet/ # 패킷 정의 (서버와 동일 프로토콜)
│ │ ├── PacketHeader.cs # PacketCode Enum
│ │ ├── PacketBody.cs # Protobuf 패킷 클래스
│ │ └── PacketSerializer.cs # 직렬화 유틸
│ │
│ └── Utils/
│ └── CrashDumpHandler.cs # 크래시 로그 + 힙 덤프
└── TempServer/ # 간이 에코 서버 (독립 테스트용)
└── Program.cs
```
---
## 3. 사용방법
### 3.1 대화형 모드
```bash
dotnet run
```
```
========== 더미 클라 테스터 ==========
1. 에코 서버
2. 더미 클라(이동만)
3. 스트레스 테스트 (부하)
====================================
1 / 2 / 3 :
```
| 모드 | 설명 |
|------|------|
| 1. 에코 서버 | Echo 패킷 송수신, RTT(Round-Trip Time) 측정 |
| 2. 더미 클라 | 이동(Transform) 패킷 전송, 패킷 손실률 측정 |
| 3. 스트레스 테스트 | Ramp-up + 이동 + Echo 동시, 퍼센타일 레이턴시, CSV 내보내기 |
### 3.2 CLI 모드 (스트레스 테스트)
```bash
# 기본 실행 (50명, 60초)
dotnet run -- stress
# 100명 클라이언트, 120초 테스트
dotnet run -- stress -c 100 -d 120
# 원격 서버 대상, 커스텀 설정
dotnet run -- stress -c 200 -d 60 -r 500 -b 20 --ip 192.168.0.10 --port 9500
# 도움말
dotnet run -- --help
```
#### CLI 옵션
| 옵션 | 축약 | 기본값 | 설명 |
|------|------|--------|------|
| `--clients` | `-c` | 50 | 총 클라이언트 수 |
| `--duration` | `-d` | 60 | 테스트 지속 시간 (초, 0=무제한) |
| `--interval` | `-i` | 100 | 패킷 전송 주기 (ms) |
| `--ramp` | `-r` | 1000 | Ramp-up 간격 (ms) |
| `--batch` | `-b` | 10 | Ramp-up 당 추가 클라이언트 수 |
| `--ip` | | localhost | 서버 IP 주소 |
| `--port` | | 9500 | 서버 포트 |
### 3.3 출력 파일
| 경로 | 내용 |
|------|------|
| `logs2/log_{timestamp}.txt` | 전체 실행 로그 |
| `results/stress_{N}clients_{timestamp}.csv` | 스트레스 테스트 결과 (클라이언트별 통계) |
| `crashes/crash_{timestamp}.log` | 크래시 스택 트레이스 |
| `crashes/crash_{timestamp}.dmp` | 힙 덤프 (Release 빌드만) |
---
## 4. 파이프라인
### 4.1 에코 테스트 (모드 1)
```
[클라이언트 N개 동시 생성]
[연결] UDP Connect → ServerBase.OnConnectionRequest()
[PollLoop] 10ms 주기로 네트워크 이벤트 처리
[SendLoop] 100ms 주기로 Echo 패킷 전송
[송신] EchoPacket { Str = "Echo seq:{N}" }
→ PacketSerializer.Serialize()
→ 4바이트 헤더(type + size) + Protobuf 페이로드
→ DeliveryMethod.ReliableUnordered
[수신] 서버가 Echo 패킷 그대로 반환
→ seq 번호로 pendingPings 조회
→ RTT 계산: (수신시각 - 송신시각) / Stopwatch.Frequency
[통계] 클라이언트별: AvgRTT, LastRTT, Sent, Recv, PacketLoss%
전체: 총 Sent/Recv, 평균 RTT
```
### 4.2 이동 테스트 (모드 2)
```
[클라이언트 N개 동시 생성]
[연결 + 인증]
DummyAccTokenPacket { Token = clientId }
→ DeliveryMethod.ReliableOrdered
[이동 시뮬레이션 - UpdateDummy()]
┌────────────────────────────────────────┐
│ 1. 델타 타임 계산 (Stopwatch) │
│ 2. 남은 거리 = 0 이면: │
│ - 벽 근처? → 반대 방향 회전 │
│ - 아니면 → 현재 방향 ±30도 랜덤 회전 │
│ - 목표 거리 = moveSpeed × (3~12초) │
│ 3. 이번 틱 이동 (moveSpeed × delta) │
│ 4. MapBounds.Clamp() → 벽 충돌 처리 │
└────────────────────────────────────────┘
[송신] TransformPlayerPacket { PlayerId, Position(X,0,Z), RotY }
→ DeliveryMethod.Unreliable (손실 감수)
[통계] 클라이언트별: Sent, Recv, PacketLoss%
```
### 4.3 스트레스 테스트 (모드 3 / CLI)
```
[설정 입력] CLI 인자 또는 대화형 입력
[Ramp-up Loop]
┌────────────────────────────────────┐
│ rampInterval(1000ms)마다 │
│ clientsPerRamp(10)명씩 클라이언트 생성 │
│ → totalClients 도달 시 중단 │
└────────────────────────────────────┘
↓ (병렬 실행)
[PollLoop] 10ms 주기 네트워크 이벤트
[SendLoop] sendInterval(100ms) 주기
├─ UpdateAndSendTransform() (이동 - Unreliable)
└─ SendPing() (Echo - ReliableUnordered)
[StatsLoop] 10초마다 실시간 통계 출력
[지속시간 만료 또는 Ctrl+C]
[최종 리포트]
├─ 처리량: 총 Sent/Recv, 패킷/초
├─ 레이턴시: Min, Avg, P50, P95, P99, Max
├─ 최악 RTT 상위 5 클라이언트 상세
└─ CSV 파일 자동 저장
```
### 4.4 패킷 직렬화 파이프라인
```
객체 (e.g. TransformPlayerPacket)
protobuf-net Serialize → byte[] payload
PacketSerializer.Serialize()
┌──────────────────────────────┐
│ [2B type] [2B size] [payload] │
│ ushort ushort byte[] │
└──────────────────────────────┘
NetDataWriter.Put(data)
peer.Send(writer, DeliveryMethod)
```
---
## 5. 테스트 모드별 기능 비교
| 기능 | 에코 (1) | 이동 (2) | 스트레스 (3) |
|------|:--------:|:--------:|:------------:|
| 동시접속 클라이언트 | 10 (고정) | 10 (고정) | N (설정 가능) |
| 인증 패킷 전송 | X | O | O |
| 이동 시뮬레이션 | X | O | O |
| Echo RTT 측정 | O | X | O |
| 패킷 손실 추적 | O | O | O |
| 점진적 Ramp-up | X | X | O |
| 지속시간 제한 | 무제한 | 무제한 | 설정 가능 |
| 실시간 통계 | X | X | O (10초 주기) |
| 퍼센타일 레이턴시 | X (평균만) | X | O (P50/P95/P99) |
| CSV 내보내기 | X | X | O |
| CLI 인자 | X | X | O |
| 최악 클라이언트 분석 | X | X | O (상위 5) |
---
## 6. 구현 진행도
### 완료
| 항목 | 상태 | 설명 |
|------|:----:|------|
| Echo RTT 측정 | **완료** | seq 기반 ping/pong, Stopwatch 고정밀 타이머 |
| 더미 이동 시뮬레이션 | **완료** | 벽 충돌, 랜덤 방향 전환, 델타 타임 기반 이동 |
| 맵 경계 처리 | **완료** | MapBounds (Clamp, 벽 반대 방향 계산) |
| 패킷 손실 추적 | **완료** | LiteNetLib.NetStatistics 활용 |
| 크래시 덤프 | **완료** | Debug: .log / Release: .log + .dmp |
| 로깅 (콘솔+파일) | **완료** | Serilog 타임스탬프별 로그 파일 |
| Graceful Shutdown | **완료** | Ctrl+C → CancellationToken → 통계 출력 후 종료 |
| 스트레스 테스트 | **완료** | Ramp-up, 퍼센타일, CSV, CLI 인자 |
| CLI 인자 지원 | **완료** | `stress -c N -d T --ip --port` |
### 미구현 / 향후 작업
| 항목 | 상태 | 설명 |
|------|:----:|------|
| 채널 입장 시뮬레이션 | 미구현 | INTO_CHANNEL 패킷 전송 후 게임 루프 진입 |
| 전투 액션 시뮬레이션 | 미구현 | ACTION_PLAYER (공격/스킬) 패킷 전송 |
| 상태 변경 시뮬레이션 | 미구현 | STATE_PLAYER (HP/MP) 패킷 전송 |
| JWT 토큰 인증 테스트 | 미구현 | ACC_TOKEN 방식 인증 플로우 검증 |
| 서버 응답 검증 | 미구현 | 수신 패킷 내용 파싱 및 정합성 체크 |
| 테스트 시나리오 스크립트 | 미구현 | JSON/YAML 기반 테스트 시나리오 정의 |
| 그래프 출력 | 미구현 | RTT/처리량 시계열 차트 생성 |
---
## 7. 설정 참고
### 서버 연결 기본값
| 항목 | 값 |
|------|-----|
| IP | `localhost` |
| Port | `9500` |
| Connection Key | `test` |
### 이동 시뮬레이션 파라미터
| 항목 | 값 | 설명 |
|------|-----|------|
| moveSpeed | 3.5 | 이동 속도 (units/sec) |
| 맵 범위 | -50 ~ 50 (X, Z) | 100x100 영역 |
| 벽 감지 마진 | 0.5 | 벽 근처 판정 거리 |
| 목표 거리 | moveSpeed x 3~12초 | 직진 후 방향 전환 |
| 방향 전환 | 현재 ±30도 랜덤 | 벽 근처 시 반대 방향 강제 |
### 스트레스 테스트 기본값
| 항목 | 값 | 설명 |
|------|-----|------|
| 클라이언트 수 | 50 | `-c` 옵션 |
| 지속 시간 | 60초 | `-d` 옵션 |
| 전송 주기 | 100ms | `-i` 옵션 |
| Ramp-up 간격 | 1000ms | `-r` 옵션 |
| Ramp-up 배치 | 10명 | `-b` 옵션 |
| 실시간 통계 주기 | 10초 | 고정 |
| Echo 최대 pending | 500 | 메모리 누수 방지 |