srs/docs/proxy/proxy-load-balancer.md
Winlin 6ee6f1ca5f Proxy: Refactor for testability; add SRT/WHIP E2E and unit tests. v7.0.148 (#4675)
- Refactor the Go proxy for dependency injection: every proxy server,
the bootstrap, the signal handler, the load balancers, and AMF0 now accept
functional-option seams (factories/closures) so tests can inject fakes
without binding real sockets, talking to real Redis, or racing on
package globals.

- Drop the package-global `lb.SrsLoadBalancer`. The bootstrap creates
the LB locally and threads it through every proxy server constructor. Two old
global indirections in `internal/signal` and `internal/rtmp/amf0` are
likewise replaced by per-instance fields.

- Rename `internal/server` → `internal/proxy` and rename the `lb` public
surface for clarity: `SRSLoadBalancer` is split into `OriginService` /
`HLSService` / `RTCService` and recomposed as `OriginLoadBalancer`;
`SRSServer` → `OriginServer`; all proxy server types gain a `Proxy`
qualifier (e.g. `RTMPServer` → `RTMPProxyServer`).

- Extract the Redis client behind a new `internal/redisclient` package
with a minimal `RedisClient` interface and a counterfeiter fake.

- Add counterfeiter fakes (`proxyfakes`, `lbfakes`, `redisclientfakes`)
and ~7.5k lines of unit tests covering bootstrap, memory + Redis LBs, all
five proxy servers, the signal handler, and AMF0.

- Add two new E2E flows — `proxy-e2e-srt-test.sh` (SRT publish through
proxy, verify SRT/RTMP/HTTP-FLV/HLS playback) and `proxy-e2e-whip-test.sh`
(WHIP publish, verify RTMP/HTTP-FLV/HLS via origin `rtc_to_rtmp`) — plus
`setup-ffmpeg-with-whip.sh`, a macOS builder for an ffmpeg with
openssl-DTLS WHIP and SRT support that the two scripts auto-invoke when needed.

- Workspace reorg: move `memory/` and `skills/` to the repo root so all
agent tools (Claude / Codex / Kiro / OpenClaw) share one source of truth via
symlinks. Sync `docs/proxy/proxy-load-balancer.md` and
`memory/srs-codebase-map.md` with the new names.

No protocol, log, HTTP API, or wire-format changes. Refactor only — all
  externally observable proxy behavior is unchanged.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
2026-05-17 12:09:07 -04:00

5.3 KiB

Load Balancer

Overview

The proxy load balancer distributes client streams across multiple backend origin servers. It provides a pluggable interface with two implementations:

  1. Memory Load Balancer - For single proxy deployments
  2. Redis Load Balancer - For multi-proxy deployments with shared state

Both implementations maintain stream-to-server mappings to ensure stream consistency - once a stream is assigned to a backend server, all subsequent requests for that stream route to the same server.

Core Responsibilities

  1. Server Management

Backend Server Registration:

  • Origin servers register themselves with the proxy via System API
  • Servers provide their endpoints for each protocol (RTMP, HTTP, WebRTC, SRT)
  • Registration includes server identity (ServerID, ServiceID, PID)
  • Heartbeat mechanism maintains server health status

Server Selection:

  • Pick appropriate backend server for new streams
  • Consider server health (last heartbeat time)
  • Random selection from healthy servers for load distribution
  • Maintain stream-to-server mapping for consistency
  1. Stream State Management

Protocol-Specific State:

  • HLS Streams: Dual-index storage for M3U8 playlists and TS segments

    • Index by stream URL for initial playlist requests
    • Index by SPBHID (SRS Proxy Backend HLS ID) for segment requests
  • WebRTC Connections: Dual-index for session management

    • Index by stream URL for initial connection setup
    • Index by ufrag (ICE username) for STUN binding requests
  1. Load Balancing Strategy

Stream-Level Stickiness:

  • First request for a stream selects a backend server
  • All subsequent requests for that stream use the same server
  • Ensures session continuity and state consistency on backend

Health-Based Selection:

  • Only consider servers with recent heartbeats (within 300 seconds)
  • Fallback to any registered server if no healthy servers available
  • Random selection among healthy servers for even distribution

Architecture

The load balancer uses a clean interface-based architecture:

Core Interface: OriginLoadBalancer

  • Initialization and lifecycle management
  • Server registration and updates
  • Stream routing (Pick operation)
  • Protocol-specific state management (HLS, WebRTC)

Data Models:

  • OriginServer: Backend origin server representation
  • HLSPlayStream: Interface for HLS streaming sessions
  • RTCConnection: Interface for WebRTC connections

Memory Load Balancer

  1. Design

Storage: In-memory maps for fast access

  • Server registry with thread-safe concurrent access
  • Stream-to-server mappings
  • Protocol-specific session state (HLS, WebRTC)

Use Case: Single proxy instance handling moderate stream counts

Characteristics:

  • Lowest latency (no network operations)
  • Simple deployment (no external dependencies)
  • State limited to single proxy instance
  • Best for deployments where proxy isn't the bottleneck
  1. Configuration
PROXY_LOAD_BALANCER_TYPE=memory

Redis Load Balancer

  1. Design

Storage: Shared Redis instance for distributed state

  • All proxies read/write to same Redis
  • TTL-based expiration for automatic cleanup
  • JSON serialization for cross-process communication

Use Case: Multiple proxy instances sharing load

Characteristics:

  • Enables horizontal scaling of proxies
  • Higher latency (network + serialization overhead)
  • Requires Redis infrastructure
  • Best for large deployments with many streams
  1. Configuration
PROXY_LOAD_BALANCER_TYPE=redis
PROXY_REDIS_HOST=127.0.0.1
PROXY_REDIS_PORT=6379
PROXY_REDIS_PASSWORD=
PROXY_REDIS_DB=0
  1. Redis Key Design

Server Keys:

  • srs-proxy-server:{serverID} - Server registration (300s TTL)
  • srs-proxy-all-servers - Server list index (no expiration)

Stream Mapping Keys:

  • srs-proxy-url:{streamURL} - Stream-to-server mapping (no expiration)

Session State Keys:

  • srs-proxy-hls:{streamURL} - HLS by URL (120s TTL)
  • srs-proxy-spbhid:{spbhid} - HLS by SPBHID (120s TTL)
  • srs-proxy-rtc:{streamURL} - WebRTC by URL (120s TTL)
  • srs-proxy-ufrag:{ufrag} - WebRTC by ufrag (120s TTL)

Expiration and Cleanup

Server Heartbeat: 300 seconds

  • Servers must send updates every 30 seconds (recommended)
  • Considered dead if no update within 300 seconds
  • Memory LB: filtered during selection
  • Redis LB: automatic TTL expiration

Session State: 120 seconds

  • HLS and WebRTC sessions expire after 120 seconds of inactivity
  • Automatic cleanup via TTL (Redis) or garbage collection (Memory)
  • Sessions renewed on each request

Stream Mappings: No expiration

  • Stream-to-server mappings persist indefinitely
  • Ensures consistent routing for long-running streams
  • Only reset when backend server dies or mapping explicitly cleared

Comparison: Memory vs Redis

Aspect Memory Load Balancer Redis Load Balancer
Deployment Single proxy Multiple proxies
State Storage Local memory Shared Redis
Latency Lowest (in-process) Network + serialization
Scalability Single instance Horizontal scaling
Dependencies None Redis required
Complexity Simple Moderate
Fault Tolerance Single point of failure Multiple proxies
Best For Moderate traffic High traffic, high availability