콘텐츠로 이동

성능 가이드

이 가이드는 실제 구현된 성능 제어 항목과 측정 우선 튜닝 절차를 설명합니다. 종단 간 지연과 처리량은 주로 선택한 모델, 제공자, 네트워크, 요청 크기, 스트리밍 동작, 활성 미들웨어, 호스트 한도에 따라 달라집니다. 프로젝트는 모든 환경에 적용되는 초당 요청 수나 메모리 목표를 보장하지 않습니다.

튜닝 전 측정

저장소의 benches/ 아래에 Criterion 벤치마크가 있습니다.

cargo bench
cargo bench --bench sse_pipeline_micro

프로덕션과 동일한 대상 및 기능 세트에서 실행하십시오. HTTP 부하 테스트에는 실제 요청 본문, 인증 모드, 백엔드 구성을 사용해야 합니다. /health 벤치마크는 프록시 트래픽을 대표하지 않습니다.

wrk POST 스크립트 예시:

-- scripts/chat_completion.lua
wrk.method = "POST"
wrk.body = '{"model":"gpt-5.4-nano","messages":[{"role":"user","content":"Hello"}]}'
wrk.headers["Content-Type"] = "application/json"
wrk -t12 -c400 -d30s --latency \
  -s scripts/chat_completion.lua \
  http://localhost:8080/v1/chat/completions

같은 요청을 백엔드에 직접 보내 기준값을 만드십시오. 다른 호스트에서 복사한 수치보다 직접 호출과 라우터 경유 호출의 차이가 더 의미 있습니다.

SSE 파이프라인 벤치마크

모든 /v1/chat/completions SSE 응답은 청크 기한, UTF-8 경계 처리, SSE 파싱, 추론 필드 정규화, 오류 변환, keep-alive 삽입, 직렬화를 위한 공통 build_sse_pipeline 어댑터를 사용합니다.

Apple M1 Ultra(macOS 26.5, rustc 1.95, 벤치마크 스레드 1개)에서 저장소 벤치마크를 실행한 결과는 다음과 같습니다.

청크 단순 스트림 전체 파이프라인 파이프라인 비용 청크당
64 5.36 µs 54.8 µs 49.4 µs 0.77 µs
512 42.5 µs 429 µs 387 µs 0.76 µs
4096 349 µs 3.47 ms 3.12 ms 0.76 µs

이는 단일 호스트의 마이크로벤치마크 결과이며 서비스 수준 보장이 아닙니다. 배포할 릴리스, 컴파일러, 아키텍처, 기능 세트에서 다시 측정하십시오.

애플리케이션 제어 항목

연결 풀

server.connection_pool_size는 백엔드마다 유지할 최대 유휴 HTTP 연결 수를 설정합니다. 측정 결과 연결 churn 또는 재사용 부족이 확인될 때만 늘리십시오. 유휴 연결도 자원을 사용합니다.

server:
  connection_pool_size: 100

일회성 CLI 덮어쓰기는 다음과 같습니다.

continuum-router --config config.yaml --connection-pool-size 100

라우터는 시작할 때 백엔드 연결을 미리 준비합니다. 공유 HTTP 클라이언트 재사용은 핸드셰이크 비용을 줄이지만 실제 효과는 제공자와 네트워크에 따라 달라집니다.

백엔드 선택

최상위 selection_strategy 필드를 사용하십시오. routing.strategy는 프로덕션 백엔드 선택 제어가 아닙니다.

selection_strategy: LeastLatency

backends:
  - name: primary
    url: http://backend-1:8000
    weight: 3
  - name: secondary
    url: http://backend-2:8000
    weight: 1

사용 가능한 값:

  • RoundRobin
  • WeightedRoundRobin
  • LeastLatency
  • Random
  • ConsistentHash
  • PrefixAwareHash

LeastLatency는 관측된 백엔드 지연을 사용합니다. WeightedRoundRobin은 각 백엔드의 weight를 사용합니다. ConsistentHash는 안정적인 affinity를 제공하고, PrefixAwareHash는 프롬프트 접두사 affinity와 prefix_routing 설정을 사용해 분산 KV 캐시 재사용을 높입니다.

시간 초과

느린 제공자 작업을 기다리는 것보다 포기하는 편이 나을 때만 시간 초과를 줄이십시오. 클라이언트 전체 기한은 라우터 재시도 및 요청 예산보다 길게 설정하십시오.

timeouts:
  connection: 10s
  request:
    standard:
      first_byte: 30s
      total: 180s
    streaming:
      first_byte: 60s
      chunk_interval: 30s
      total: 600s

재시도

재시도는 일시적 장애 복구를 개선하지만 작업량과 꼬리 지연을 늘립니다. 제공자 안정성을 검증한 뒤 저지연 배포에서 시도 횟수를 줄일 수 있습니다.

retry:
  max_attempts: 2
  initial_delay: 100ms
  max_delay: 2s
  backoff_multiplier: 2.0
  jitter: true
  retryable_status_codes: [429, 502, 503, 504]
  retryable_errors: [ConnectionError, TimeoutError]
  timeout: 10s

상태 확인

검사 주기가 짧으면 장애를 더 빨리 감지하지만 주기적인 제공자 트래픽이 늘어납니다.

health_checks:
  enabled: true
  interval: 30s
  timeout: 5s
  unhealthy_threshold: 3
  healthy_threshold: 2

응답 캐시

선택적 응답 캐시는 적격 결정론 요청을 제공해 백엔드 호출을 줄일 수 있습니다. 측정된 항목 크기와 적중률을 기준으로 크기를 정하십시오.

response_cache:
  enabled: true
  backend: memory
  capacity: 1000
  ttl: 5m
  max_response_size: 1048576

Redis 및 계층형 백엔드는 해당 빌드 기능과 설정이 필요합니다. 활성화 전 고급 설정을 참고하십시오.

모델 목록 캐시

모델 집계는 60초 하드 TTL, 80% 소프트 TTL, stale-while-revalidate, 요청 병합, 10초 백그라운드 검사 주기, 제한된 빈 결과 백오프를 사용합니다. 이 내부 값은 설정할 수 없습니다. POST /v1/models/refresh는 속도 제한된 즉시 새로고침을 수행합니다.

프로필 예시

다음은 출발점일 뿐 모든 환경의 최적값이 아닙니다. 각 프로필을 continuum-router config validate와 대표 부하 테스트로 검증하십시오.

낮은 꼬리 지연

selection_strategy: LeastLatency

server:
  bind_address: 0.0.0.0:8080
  connection_pool_size: 100

retry:
  max_attempts: 1
  initial_delay: 100ms
  max_delay: 1s
  backoff_multiplier: 2.0
  jitter: true
  retryable_status_codes: [429, 502, 503, 504]
  retryable_errors: [ConnectionError, TimeoutError]
  timeout: 5s

health_checks:
  enabled: true
  interval: 10s
  timeout: 5s
  unhealthy_threshold: 3
  healthy_threshold: 2

작은 유휴 자원 사용량

server:
  connection_pool_size: 10

response_cache:
  enabled: false

logging:
  level: warn
  format: json

높은 동시성

server:
  connection_pool_size: 500
  # 도착뿐 아니라 상주도 묶습니다. 컨테이너 메모리 상한을 기준으로 잡으십시오.
  # 배포 가이드의 용량 산정 절을 참고하십시오.
  max_concurrent_requests: 256

rate_limiting:
  enabled: true
  storage: memory

프로덕션에서는 부분 블록을 그대로 복사하지 말고 속도 제한 정책을 완성하십시오. 속도 제한을 참고하십시오. connection_pool_size는 백엔드별 아웃바운드 풀이라 인바운드 동시성을 묶지 않습니다. 그 역할은 max_concurrent_requests가 하며, 상한을 넘으면 대기열에 넣지 않고 503Retry-After로 흘려보냅니다. 컨테이너 메모리 상한도 같은 변경에서 함께 올리십시오. 둘은 하나의 결정입니다.

Prometheus 모니터링

metrics로 컴파일하고 런타임에서 활성화하면 설정된 엔드포인트에서 Prometheus 메트릭을 제공합니다.

metrics:
  enabled: true
  endpoint: /metrics
  auth:
    enabled: true
    username: metrics
    password: "${METRICS_PASSWORD}"

유용한 메트릭:

  • http_requests_total
  • http_request_duration_seconds
  • backend_healthy
  • backend_current_load
  • http_active_connections

기능 제한 서브시스템은 컴파일되고 활성화된 경우에만 메트릭을 추가하므로 대시보드를 만들기 전 실행 중인 /metrics 출력을 확인하십시오.

쿼리 예시:

rate(http_requests_total[5m])
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))
backend_healthy
backend_current_load

운영체제 한도

높은 동시성에서는 변경 전에 파일 디스크립터와 listen backlog 한도를 확인하십시오.

ulimit -n
sysctl net.core.somaxconn
ss -s

호스트 수준 sysctl 또는 보안 한도 변경은 운영체제, 커널, 컨테이너 런타임, 트래픽 패턴에 맞게 테스트한 후 적용하십시오. 프로젝트는 하나의 보편적인 커널 튜닝 프로필을 요구하지 않습니다.

병목 진단

높은 지연

  1. 동일한 요청을 선택된 백엔드에 직접 보내 비교합니다.
  2. Admin 자격 증명으로 /admin/health/admin/circuit/all을 확인합니다.
  3. http_request_duration_seconds와 백엔드 지연/부하 메트릭을 확인합니다.
  4. 재시도 및 시간 초과 예산이 꼬리 지연을 배가하지 않는지 확인합니다.
  5. 필요한 범위에만 일시적으로 RUST_LOG=continuum_router=debug를 사용하고 비밀을 기록하지 않습니다.

높은 메모리 사용량

  1. 워크로드를 재현하며 상주 메모리를 측정합니다.
  2. 요청 속도보다 먼저 동시 처리 중인 요청 수를 봅니다. 최악의 상주 메모리는 동시성 곱하기 요청당 예산이며, 속도 제한은 단위 시간당 도착을 묶을 뿐 동시에 상주하는 수를 묶지 않습니다. 평균 30초라면 초당 10건은 약 300건이 동시에 떠 있다는 뜻입니다. 컨트롤 플레인 supply 보고의 active_requests와 in-flight 게이지를 확인하십시오.
  3. server.max_concurrent_requests가 비어 있다면 설정합니다. 이 값이 없으면 동시성 항을 묶는 것이 아무것도 없으므로, 요청당 예산이 프로세스 단위 상한을 전혀 함의하지 못합니다. 요청당 항목과 계산은 용량 산정: 메모리를 참고하십시오.
  4. 요청/응답 크기, 동시 스트림, 응답 캐시 용량을 확인합니다. Files API 전송은 디스크로 스트리밍되어 files.max_file_size와 무관하게 건당 64 KiB 버퍼만 쓰므로, 단일 메모리 항목 중 가장 큰 것은 요청당 해석된 파일 내용(원본 32 MiB, base64 확장 후 약 43 MiB)입니다.
  5. response_cache.capacity를 줄이거나 응답 캐시를 비활성화해 비교합니다.
  6. 플랫폼에 맞는 할당자/프로파일러로 릴리스 바이너리를 분석합니다.

모델 목록 캐시 용량은 내부 값이며 설정할 수 없습니다.

낮은 처리량

  1. 제공자 처리량을 직접 비교합니다.
  2. 속도 제한 거부, 서킷 상태, 백엔드 상태, 진행 중 부하를 확인합니다.
  3. connection_pool_size를 늘리기 전에 연결 재사용과 파일 디스크립터 한도를 확인합니다.
  4. 스트리밍과 비스트리밍 워크로드를 별도로 테스트합니다.
  5. 공유 상태/스토리지 선택이 다중 인스턴스에 적합한지 확인한 뒤 수평 확장합니다.

같이 보기