PhantomFlow : High-performance HTTP request simulator

이순간·2025년 7월 18일
3

MyOwnWeapon

목록 보기
4/12
post-thumbnail

KlickLab의 데이터 파이프라인은 고객의 모든 상호작용을 분석하는 것을 목표로 한다.
이는 대규모 트래픽을 지연 없이 처리해야 한다는 것을 의미했다.

시스템이 과연 피크 타임의 부하를 견딜 수 있는지,
병목 지점은 어디인지에 대한 답을 찾기 위해
실제와 같은 트래픽을 시뮬레이션할 강력한 도구가 필요했다.

그래서 우리는 자체적인 트래픽 생성 도구.
팬텀 플로우를 만들었다.


Version 1: simulate_launcher_cluster.js

초기 버전은 익숙하고 생산성이 높은 Node.js의 cluster 모듈을 활용해 멀티코어 기반의 트래픽 생성기로 만들어졌다. 간단한 테스트에는 충분했으나, 목표 성능을 향해 나아가면서 몇 가지 명확한 한계에 부딪혔다.

  • 높은 동시성에서의 RPS 불안정: 워커 수를 늘릴수록 성능이 선형적으로 증가하지 않고,
    특정 지점부터는 오히려 불안정해지는 현상이 발생했다.
  • 이벤트 루프 병목: CPU 집약적인 작업이 이벤트 루프에 부담을 주어 전체 처리량을 저하시켰다.
  • 제한적인 제어: 수천 개의 동시 연결에 대한 세밀한 제어가 어려웠다.
  • 성능 분석의 어려움: 내장된 프로파일링 기능이 부족했다.

운영체제(Windows) 자체의 한계

개발 및 초기 테스트는 주로 Windows 환경에서 이루어졌으며,
이로 인해 다음과 같은 운영체제 수준의 제약도 성능에 영향을 주었다.

  • 소켓 핸들 수 제한: Windows는 리눅스에 비해 동시에 열 수 있는 소켓(파일 디스크립터)의 수에 제한이 크고,
    커널 튜닝 여지도 적어 고부하 상황에 대응하기 어렵다.
  • 타이머 정밀도 문제: 고해상도 타이머가 필요한 경우에도 Windows는 정밀한 이벤트 스케줄링이 어렵고, 이는 고속 요청 분산에 영향을 줬다.
  • 네트워크 스택의 부하 내성 부족: Linux의 epoll에 비해 Windows의 IOCP 모델은 고성능 네트워크 처리를 위해 더 많은 설정과 관리가 필요했고, 예상보다 일찍 병목이 발생했다.
  • 프로세스 간 통신(IPC) 비용: Node.js의 cluster 모델에서 워커 간 메시지 전달 성능이 Windows에서는 Linux 대비 더 낮게 나타났다.

이러한 제약은 도구의 실제 성능과 확장성을 측정하는 데 장애 요소로 작용했으며, 이후 Linux 환경으로의 전환을 결정하게 된 또 하나의 계기가 되었다.


전환점 1: Go 언어

시스템의 한계를 돌파하기 위해 언어와 아키텍처를 재검토했고,
Go는 모든 요구사항에 대한 명쾌한 해답을 제시했다.

  • 고루틴 기반의 압도적인 동시성
  • 정교한 HTTP 클라이언트 제어
  • 내장 프로파일링 도구 pprof

전환점 2: Windows -> Linux

초기 개발은 Windows에서 이루어졌으나,
고부하 테스트를 진행하며 운영체제 수준의 명확한 한계에 직면했다.

  • 네트워크 성능: Linux의 epoll 모델은 Windows의 IOCP에 비해
    고성능 네트워크 처리에 더 최적화되어 있으며, 적은 커널 튜닝으로도 높은 성능을 보장한다.

  • 자원 관리 한계: Windows는 동시에 열 수 있는 소켓 핸들 수에 대한 제약이 더 크다.
    수만 개의 동시 연결을 시뮬레이션해야 하는 상황에서 이는 명백한 병목점으로 작용했다.


Version 2: PhantomFlow.Go

PhantomFlow는 Go로 재작성된 CLI 기반의 고성능 트래픽 시뮬레이터이다.

주요 목적

  • 실제 클릭스트림과 유사한, 고유하고 동적인 이벤트 데이터를 실시간으로 생성
  • 수천~수만 RPS 수준의 고속 트래픽을 안정적으로 발사
  • 성공/실패 요청 수 및 RPS를 1초 단위로 출력
  • pprof로 성능 병목 분석 가능

주요 최적화 포인트

  • sync.Pool: 문자열 생성 시 GC 압력 최소화
  • 고유 시드: 데이터 중복 방지
  • 커스텀 http.Transport: 연결 수 조정 및 안정성 강화
  • KST 타임스탬프: 로그 시간 비교 용이

실행 예시

빌드

go build phantomflow.go

실행

# 시간 기반 모드 (5분 동안 512 워커로 실행)
./phantomflow -d 300 -c 512 http://YOUR-NLB-ENDPOINT/api/analytics/collect

# 요청 수 기반 모드 (100만 개 요청, 256 워커로 실행)
./phantomflow -n 1000000 -c 256 http://YOUR-NLB-ENDPOINT/api/analytics/collect

출력 예시

2025-07-18 21:30:01 [진행] 성공: 153024, 실패: 18, RPS: 5098.12
2025-07-18 21:30:02 [진행] 성공: 158210, 실패: 18, RPS: 5186.00

pprof를 활용한 실시간 성능 분석

코드에 포함된 pprof 서버 덕분에 부하 테스트 중에도 PhantomFlow의 내부를 들여다볼 수 있다.

// 단 한 줄로 활성화되는 강력한 프로파일링 서버
go func() {
  _ = http.ListenAndServe("localhost:6060", nil)
}()

SSH 터널링 예시 (EC2 환경)

ssh -L 6060:localhost:6060 -i your-key.pem ubuntu@your-ec2-ip

이후 브라우저에서 아래 주소로 접속

http://localhost:6060/debug/pprof/

결론

Node.js로 시작하여 Go로 전환하고, AWS 환경에 맞춰 최적화하는 과정을 통해
PhantomFlow는 KlickLab의 데이터 수집 파이프라인을 검증하는 핵심 도구가 되었다.

이 도구는 인프라의 한계를 사전에 파악하고,
병목 지점을 개선하며, 사용자에게 항상 안정적인 서비스를 제공할 수 있게 해준다.

GitHub 저장소: https://github.com/Eatventory/PhantomFlow

profile
서툴지언정 늘 행동이 먼저이기를

0개의 댓글