Skip to content

K-jun98/http-sse-websocket-benchmark

Repository files navigation

Practice1 — HTTP / SSE / WebSocket 비교 프로젝트

Spring Boot 4 기반으로 HTTP, SSE, WebSocket 세 가지 통신 방식을 구현하고, Docker 격리 환경에서 서버 부하를 비교 측정하는 프로젝트입니다.

사전 준비

  • Java 21
  • Docker, Docker Compose
  • curl

프로젝트 구조

src/main/java/com/practice1/
├── http/
│   ├── MessageRequest.java          # 요청 DTO
│   ├── HttpController.java          # GET /api/hello, POST /api/message, GET /api/users/{id}
│   ├── HttpClientService.java       # WebClient로 외부 API 호출 (동기/비동기)
│   └── HttpClientController.java    # 외부 API 호출 엔드포인트
├── sse/
│   ├── SseController.java           # SseEmitter 방식 SSE
│   └── SseFluxController.java       # Flux 방식 SSE
├── websocket/
│   ├── WebSocketConfig.java         # STOMP 설정
│   ├── ChatMessage.java             # 채팅 DTO
│   └── ChatController.java          # 채팅 메시지 브로드캐스트
├── benchmark/
│   ├── BenchmarkResult.java         # 벤치마크 결과 DTO
│   ├── BenchmarkService.java        # JVM 내부 부하 측정 로직
│   └── BenchmarkController.java     # 벤치마크 엔드포인트
└── Practice1Application.java

src/main/resources/
├── static/
│   ├── sse.html                     # SSE 클라이언트 (브라우저)
│   └── chat.html                    # WebSocket 채팅 클라이언트 (브라우저)
└── application.yml

1단계: 로컬에서 서버 실행

MySQL 컨테이너 시작

docker-compose up -d mysql

서버 실행

./gradlew bootRun

동작 확인

# HTTP
curl localhost:8080/api/hello
curl -X POST -H "Content-Type: application/json" -d '{"message":"test"}' localhost:8080/api/message
curl localhost:8080/api/users/1

# 외부 API 호출 (jsonplaceholder)
curl localhost:8080/api/external/posts/1/sync
curl localhost:8080/api/external/posts/1/async

# SSE — 브라우저에서 접속
open http://localhost:8080/sse.html

# WebSocket 채팅 — 브라우저에서 접속
open http://localhost:8080/chat.html

2단계: Docker 격리 환경에서 벤치마크

앱 이미지 빌드 및 컨테이너 시작

docker-compose down
docker-compose build app
docker-compose up -d

docker-compose.yml에서 앱 컨테이너에 리소스 제한이 설정되어 있습니다:

deploy:
  resources:
    limits:
      memory: 512m
      cpus: "1.0"

서버 준비 확인

# health가 UP이 될 때까지 대기
curl localhost:8080/actuator/health

컨테이너 리소스 제한 확인

docker stats practice1-app --no-stream

출력 예시:

NAME            CPU %     MEM USAGE / LIMIT   MEM %     PIDS
practice1-app   0.15%     220.1MiB / 512MiB   42.98%    32

3단계: 벤치마크 실행

방법 A: JVM 내부 벤치마크 (BenchmarkController)

프로토콜별로 연결을 생성하고 GC 전후 JVM 힙/스레드를 측정합니다.

# 전체 프로토콜 순차 테스트 (100개 동시 연결)
curl 'localhost:8080/api/benchmark/all?connections=100' | python3 -m json.tool

# 개별 프로토콜 테스트
curl 'localhost:8080/api/benchmark/http?connections=100' | python3 -m json.tool
curl 'localhost:8080/api/benchmark/sse-emitter?connections=100' | python3 -m json.tool
curl 'localhost:8080/api/benchmark/sse-flux?connections=100' | python3 -m json.tool
curl 'localhost:8080/api/benchmark/websocket?connections=100' | python3 -m json.tool

방법 B: 외부 부하 + docker stats 측정

호스트에서 curl로 동시 연결을 생성하고, docker stats와 Actuator로 컨테이너/JVM 수준 메트릭을 동시에 수집합니다.

터미널 1 — docker stats 실시간 모니터링:

docker stats practice1-app

터미널 2 — 부하 발생 및 Actuator 측정:

CONNECTIONS=200

# Baseline 측정
curl -s localhost:8080/actuator/metrics/jvm.memory.used | python3 -m json.tool
curl -s localhost:8080/actuator/metrics/jvm.threads.live | python3 -m json.tool

# HTTP 부하 (200개 동시 요청 x 10회)
for round in $(seq 1 10); do
  for i in $(seq 1 $CONNECTIONS); do
    curl -s localhost:8080/api/hello > /dev/null &
  done
  wait
done
# → 터미널 1에서 docker stats 변화 확인
# → Actuator 다시 측정

# SSE 부하 (200개 동시 연결 유지)
for i in $(seq 1 $CONNECTIONS); do
  perl -e 'alarm 15; exec @ARGV' -- curl -s -N localhost:8080/api/sse/stream > /dev/null &
done
# → 3초 후 docker stats 확인
# → Actuator 측정

# SSE Flux 부하
for i in $(seq 1 $CONNECTIONS); do
  perl -e 'alarm 15; exec @ARGV' -- curl -s -N localhost:8080/api/sse/flux > /dev/null &
done
# → 동일하게 측정

# WebSocket (SockJS xhr_streaming) 부하
for i in $(seq 1 $CONNECTIONS); do
  SRV=$((RANDOM % 900 + 100))
  SID=$(cat /dev/urandom | LC_ALL=C tr -dc 'a-z' | head -c 8)
  perl -e 'alarm 15; exec @ARGV' -- curl -s -N "localhost:8080/ws/$SRV/$SID/xhr_streaming" > /dev/null &
done
# → 동일하게 측정

4단계: 패킷 구조 확인

각 프로토콜의 헤더 오버헤드를 확인합니다.

# HTTP — 매 요청마다 전체 헤더 교환
curl -v localhost:8080/api/hello

# SSE — 최초 1회 헤더 후 데이터만 스트리밍
perl -e 'alarm 4; exec @ARGV' -- curl -v -N localhost:8080/api/sse/stream

# WebSocket — HTTP 101 업그레이드 핸드셰이크
perl -e 'alarm 3; exec @ARGV' -- curl -v \
  -H "Upgrade: websocket" \
  -H "Connection: Upgrade" \
  -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
  -H "Sec-WebSocket-Version: 13" \
  localhost:8080/ws/websocket

5단계: 정리

docker-compose down

벤치마크 리포트

파일 설명
benchmark-report.md 로컬 JVM 내부 측정 결과 (100 연결)
benchmark-report-docker.md Docker 격리 환경 측정 결과 (200 연결, 512MB/1CPU)

About

HTTP / SSE / WebSocket 비교 프로젝트

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors