Caching und CDN für die OTT-Auslieferung

Anhang für den Betrieb großer Installationen: wie das Caching der OTT-Antworten von Perfect Streamer aufgebaut ist und wie einem Knoten ein cachender Reverse Proxy oder ein CDN vorgeschaltet wird. Auslieferungsmodi, URL-Formate und Autorisierung sind im Hauptabschnitt OTT und DVR beschrieben.

Der Server erzeugt Antworten dreier Kategorien, die sich in der Lebensdauer des Inhalts und in der Eignung für das Caching durch zwischengeschaltete Knoten (Reverse Proxy, CDN, Client-Cache) unterscheiden.

1. Caching-Modell

1.1. Ressourcen und HTTP-Header

Ressource

URL

Content-Type

Cache-Control

TS-Segment (HLS)

/h<sess>/<keyHex>.ts

video/mp2t

public, max-age=60, immutable

VTT-Segment (Untertitel)

/h<sess>/sub/<pid>/<keyHex>.vtt

text/vtt; charset=utf-8

public, max-age=60, immutable

fMP4-Segment (DASH / LL-HLS)

/h<sess>/init.mp4, /h<sess>/<key|N>.m4s

video/mp4

public, max-age=60, immutable

DASH MPD

/h<sess>/index.mpd

application/dash+xml; charset=utf-8

public, max-age=1

HLS master

/hls/<stream>/<login>/<pass>/index.m3u8

application/vnd.apple.mpegurl

public, max-age=1

HLS media

/h<sess>/index.m3u8, /h<sess>/sub/<pid>/index.m3u8

application/vnd.apple.mpegurl

public, max-age=1

302 Redirect

/dash/<stream>/<login>/<pass>/index.mpd

no-cache, no-store

Raw TS

/http/<stream>/<login>/<pass>

video/mp2t

nicht gesetzt; wird nicht gecacht

1.2. Eigenschaften der Segmente

Der hexadezimale Segmentbezeichner in der URL (<keyHex> in den Pfaden /h<sess>/<keyHex>.ts) wird als CRC64 aus der Startzeit des Segments und der Stream-ID gebildet und ist global eindeutig. Die URL des Segments adressiert unveränderlichen Inhalt — bei wiederholten Anfragen derselben URL wird ein identischer Bytestrom zurückgegeben (solange das Segment innerhalb des gleitenden Fensters bleibt).

Die Direktive immutable unterdrückt die bedingte Revalidierung durch den Client (If-None-Match, If-Modified-Since). Der Wert max-age=60 gewährleistet die Kompatibilität mit einem typischen timeShiftBufferDepth=40s.

CMAF-fMP4-Segmente (.m4s) und die gemeinsame init.mp4 für DASH / Low-Latency HLS werden analog adressiert und nach demselben Modell gecacht (immutable, max-age=60). Teilsegmente (Parts) von LL-HLS sind Byte-Range-Anfragen innerhalb derselben .m4s und bilden daher keinen eigenen Cache-Eintrag.

1.3. Eigenschaften der Manifeste

max-age=1 begrenzt die obere Schranke der Veralterung des Inhalts im Cache auf eine Sekunde. Zusammen mit proxy_cache_lock on (nginx) werden Anfragespitzen auf das Manifest zu einer Anfrage pro Sekunde an den Origin zusammengefasst.

1.4. Variabilität des Inhalts

Bei absPath=0 (Standardwert, der URL-Parameter a fehlt) enthalten die HLS-Media-Manifeste und das DASH-MPD keinen Sitzungsbezeichner im Rumpf. Der Inhalt des Manifests ist zwischen Sitzungen identisch, die zu derselben (stream, param)-Kombination gehören. Das erlaubt einem Reverse-Proxy-Cache, den Eintrag bei normalisiertem Cache-Schlüssel sitzungsübergreifend wiederzuverwenden.

Bei absPath=1 (URL-Parameter a=1) enthält der Rumpf des Manifests absolute URLs einschließlich Schema, Host und Sitzungsbezeichner. Der Inhalt wird sitzungsspezifisch, eine sitzungsübergreifende Wiederverwendung des Caches ist nicht möglich.

2. Verhalten der Clients

Client

URL der Manifest-Aktualisierung

Auswirkung auf die Anzahl der Sitzungen

HLS-Player über die Media-Playlist

/h<sess>/index.m3u8

Eine Sitzung je Wiedergabevorgang

DASH-Player über die Root-URL

/dash/<stream>/.../index.mpd (Wiederholungszyklus)

Wird durch Session Reuse behandelt (siehe 3.2)

Browser-Player (MSE)

/h<sess>/... über <Location> / Session-URL

Eine Sitzung je Wiedergabevorgang

3. Spezielle Mechanismen

3.1. HTTP 302 Redirect für DASH

Eine Anfrage der Form /dash/<stream>/<login>/<pass>/index.mpd liefert die Antwort 302 Found mit dem Header Location: /h<sess>/index.mpd. Der Antwortrumpf ist leer. Autorisierung und Zuweisung der Sitzung erfolgen bei der Verarbeitung des Redirects.

Clients, die das Caching des Redirects unterstützen, greifen in den folgenden Anfragen direkt auf die Session-URL zu. Clients, die es nicht unterstützen, wiederholen die Redirect-Anfrage. Der Aufwand für die erneute Verarbeitung des Redirects beschränkt sich auf die Authentifizierungsprüfung und die Operationen des Session Reuse.

3.2. Session Reuse für DASH

Bei der Verarbeitung einer Anfrage /dash/.../index.mpd desselben Logins an denselben Stream (mit demselben Adaptive-Merkmal) findet der Server eine bereits bestehende DASH-Sitzung und gibt deren Bezeichner erneut zurück. Es wird keine neue Sitzung angelegt und kein Slot des Limits gleichzeitiger Verbindungen verbraucht. Wiederverwendet werden nur Sitzungen im gleichen Wiedergabemodus: eine Live-Sitzung und eine VOD-Sitzung des Archivs (Parameter t/d/epg) werden nicht zusammengeführt.

Gilt nur für DASH. Für HLS ist kein eigener Reuse-Mechanismus erforderlich: HLS-Clients aktualisieren die Media-Playlist über die Session-URL und legen nicht bei jeder Aktualisierung eine neue Sitzung an.

3.3. Wiederverwendung von Segmenten zwischen Sitzungen

Der Pfad /h<sess>/<keyHex>.ts hängt bei der Auflösung von <keyHex> zum Inhalt nicht von <sess> ab: <keyHex> identifiziert das TS-Segment innerhalb des Streams global eindeutig. Nginx mit normalisiertem Cache Key (der das Präfix /h<sess>/ abschneidet) bedient alle Anfragen desselben <keyHex> aus einem einzigen Cache-Eintrag, unabhängig davon, welche Clients sie gestellt haben.

Die Deduplizierung ist nur auf content-addressed Namen anwendbar — auf Segmente mit einem 16-stelligen hexadezimalen Bezeichner (.ts, .m4s mit <keyHex>, .vtt). Nummerierte Segmente von Live-DASH (<Nummer>.m4s), init.mp4 und die Manifeste sind nur innerhalb ihrer Sitzung eindeutig — ihr Cache-Schlüssel muss das Präfix /h<sess>/ beibehalten, sonst liefert der Cache den Inhalt eines Streams an die Zuschauer eines anderen. Für DASH sorgt Session Reuse für die Deduplizierung der Manifeste zwischen Clients desselben Logins (siehe 3.2).

4. Anfrageparameter

Parameter

Standardwert

Wirkung

a

0

1 — absolute URLs in den Manifesten; 0 — relative

s

40

timeShiftBufferDepth in Sekunden

m

40

Minimale Fensterlänge für die Ausgabe des Manifests

v

6 für die OTT-Modi, 3 für Peering / HLS

#EXT-X-VERSION in HLS (wird von DASH ignoriert); ein explizit in der URL angegebener Wert überschreibt den Standardwert

h3

nicht vorhanden (off)

Opt-in für HTTP/3 (QUIC): veranlasst den Server, Alt-Svc in der Antwort auszugeben; sticky auf der Session-URL. Siehe HTTP/3 (QUIC)

Die Änderung eines Parameters über den Query String aktualisiert die in der Sitzung gespeicherten Werte beim nächsten Wiederöffnen der Sitzung. Die Parameter der Archivwiedergabe t, d und epg sind in Archivwiedergabe (VOD) beschrieben.

5. Lastcharakteristika

Die Last auf dem Origin skaliert mit der Anzahl gleichzeitig betrachteter unterschiedlicher Streams. Eine steigende Anzahl von Clients, die denselben Stream betrachten, erhöht die Anzahl der Anfragen an den Origin nicht, sofern ein Reverse-Proxy-Cache und ein normalisierter Cache Key vorhanden sind.

Szenario

Frequenz der Origin-Anfragen (Richtwert)

1 Client auf Stream X

MPD: 0.4 req/s, segment: 0.2 req/s

N Clients auf denselben Stream X (Cache aktiviert)

MPD: 1 req/s, segment: 0.2 req/s

N DASH-Clients im Wiederholungsmodus auf einem Stream

MPD: 1 req/s (mit proxy_cache_lock)

N Clients auf N unterschiedliche Streams

MPD: 0.4·N req/s, segment: 0.2·N req/s

Segmente werden global über content-addressed Namen dedupliziert; für die Deduplizierung der Manifeste zwischen Clients sorgen Session Reuse (DASH) und der Cache innerhalb der Sitzung.

6. Nginx als cachender Reverse Proxy

6.1. Basiskonfiguration

proxy_cache_path /var/cache/nginx/pss_segments
    levels=1:2 keys_zone=pss_segments:100m
    max_size=20g inactive=30m use_temp_path=off;

proxy_cache_path /var/cache/nginx/pss_manifests
    levels=1:2 keys_zone=pss_manifests:10m
    max_size=256m inactive=5m use_temp_path=off;

upstream pss_backend {
    server 127.0.0.1:43972;
    keepalive 64;
}

map $uri $pss_cache_key {
    "~^/h[0-9a-f]{16}(?<tail>(/[0-9]+)?/[0-9a-f]{16}\.(ts|m4s)|/sub/[0-9]+/[0-9a-f]{16}\.vtt)$"  "stream:$tail";
    default  $uri;
}

server {
    listen 80;
    server_name stream.example.com;

    location ~* "^/h[0-9a-f]{16}(/[0-9]+|/sub/[0-9]+)?/([0-9a-f]+\.(ts|m4s|vtt)|init\.mp4)$" {
        proxy_cache               pss_segments;
        proxy_cache_key           $pss_cache_key;
        proxy_cache_valid         200 60s;
        proxy_cache_valid         404 403 0s;
        proxy_cache_lock          on;
        proxy_cache_use_stale     updating error timeout;
        proxy_cache_revalidate    on;
        proxy_ignore_headers      Vary;
        add_header                X-Cache-Status $upstream_cache_status;

        proxy_pass                http://pss_backend;
        proxy_http_version        1.1;
        proxy_set_header          Connection "";
        proxy_buffering           on;
    }

    location ~* "(^/h[0-9a-f]{16}(/[0-9]+|/sub/[0-9]+)?/index\.(m3u8|mpd)$|^/(hls|dash|llhls)/.*\.(m3u8|mpd)$)" {
        proxy_cache               pss_manifests;
        proxy_cache_key           $pss_cache_key;
        proxy_cache_valid         200 1s;
        proxy_cache_valid         404 403 0s;
        proxy_cache_lock          on;
        proxy_cache_lock_timeout  2s;
        proxy_cache_use_stale     updating;
        add_header                X-Cache-Status $upstream_cache_status;

        proxy_pass                http://pss_backend;
        proxy_http_version        1.1;
        proxy_set_header          Connection "";
    }

    location / {
        proxy_pass                http://pss_backend;
        proxy_http_version        1.1;
        proxy_set_header          Connection "";
        proxy_set_header          X-Forwarded-Proto $scheme;
        proxy_set_header          X-Forwarded-Host  $host;
        proxy_buffering           off;
        proxy_read_timeout        3600s;
    }
}

Der Origin-Port im Beispiel ist der Standardport des Streaming-HTTP-Servers (43972; HTTPS — 43982). Normalisiert werden nur die content-addressed Namen der Segmente (siehe 3.3); Manifeste, init.mp4 und nummerierte Segmente werden unter der vollständigen URI ihrer Sitzung gecacht. Die Direktive proxy_ignore_headers Vary in der Location der Segmente ist gerechtfertigt: Der Server versieht OTT-Antworten mit dem Header Vary: Origin, und ohne sie würde der Cache nach dem Origin-Wert des Clients in Varianten aufgeteilt (siehe 7).

6.2. Zweck der Direktiven

Direktive

Zweck

proxy_cache_lock on

Serialisiert die Ausführung der Upstream-Anfragen bei gleichzeitigen Cache Misses auf denselben Schlüssel

proxy_cache_use_stale updating

Gibt parallelen Anfragen während der Cache-Aktualisierung die veraltete Kopie zurück

proxy_cache_revalidate on

Verwendet If-Modified-Since bei einem Cache Miss mit gespeicherter Kopie

proxy_cache_valid 404 403 0s

Verbietet das Caching von Autorisierungsfehlern und 404

keepalive 64 im Upstream

Unterhält einen Pool persistenter Verbindungen zum Origin

proxy_buffering on

Für Segmente; aktiviert die Pufferung der Antwort in nginx

proxy_buffering off

Für den Abschnitt /; deaktiviert die Pufferung (Raw Streaming)

6.3. Berechnung von max_size des Segment-Caches

Richtwert: bitrate × timeShiftBufferDepth × distinct_streams × 2

Beispiel: 10 Streams × 8 Mbit/s × 40 s × 2 ≈ 800 MB. Es wird empfohlen, eine Reserve von 10x für die Schwankungen der Bitrate vorzusehen.

6.4. TLS-Terminierung

Der Server Perfect Streamer nimmt Verbindungen auf dem HTTP- und dem HTTPS-Port entgegen. Bei TLS-Terminierung auf nginx verwendet der Upstream den HTTP-Port. Die Weitergabe der Header X-Forwarded-Proto und X-Forwarded-Host ist für die korrekte Bildung absoluter URLs bei absPath=1 zwingend erforderlich.

server {
    listen 443 ssl http2;
    server_name stream.example.com;

    ssl_certificate           /etc/letsencrypt/live/stream.example.com/fullchain.pem;
    ssl_certificate_key       /etc/letsencrypt/live/stream.example.com/privkey.pem;
    ssl_protocols             TLSv1.2 TLSv1.3;
    ssl_session_cache         shared:SSL:10m;
    ssl_session_timeout       1d;

    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    location ... {
        proxy_pass                http://pss_backend;
        proxy_set_header          X-Forwarded-Proto https;
        proxy_set_header          X-Forwarded-Host  $host;
        proxy_set_header          Host              $host;
        # + caching directives from 6.1
    }
}

server {
    listen 80;
    server_name stream.example.com;
    return 301 https://$host$request_uri;
}

Bei HTTPS zwischen nginx und Origin kommen die Direktiven proxy_ssl_verify und proxy_ssl_trusted_certificate zum Einsatz. Für Loopback-Verbindungen ist eine Verschlüsselung überflüssig.

6.5. Multihost

Werden mehrere server_name aus einem nginx-Prozess bedient, wird $host zur Isolierung der Inhalte in den Cache Key aufgenommen:

map $uri $pss_cache_key {
    "~^/h[0-9a-f]{16}(?<tail>(/[0-9]+)?/[0-9a-f]{16}\.(ts|m4s)|/sub/[0-9]+/[0-9a-f]{16}\.vtt)$"  "$host:stream:$tail";
    default  "$host:$uri";
}

Die Größe von keys_zone wird mit 8000 Schlüsseln/MB berechnet. Für Multihost-Installationen mit Tausenden von Streams wird keys_zone=...:300m oder höher empfohlen.

7. Client-seitiges Caching

Cache-Control: immutable wird von aktuellen Browsern verarbeitet. Der Client-Cache liefert das Segment bei erneutem Zugriff ohne bedingte Anfrage (auch beim Rückwärtssprung innerhalb des Player-Puffers).

Service Workers können anhand des Inhalts von Cache-Control die Strategie cache-first anwenden. DASH-Player nutzen MSE über SourceBuffer; ein in den Puffer eingefügtes Segment bleibt ohne erneute HTTP-Anfrage verfügbar, bis es aus dem gleitenden Fenster herausfällt.

Für Cross-Domain-Anfragen gibt der Server Access-Control-Allow-Origin: * zusammen mit dem Header Vary: Origin, Access-Control-Request-Headers aus. Ein Caching-Proxy, der Vary beachtet, teilt die Einträge nach dem Origin-Wert des Clients in Varianten auf (Browser-Player senden Origin, Konsolen-Clients nicht), was die HIT rate senkt. Da ACAO das universelle „*“ ist, kann in der Location der Segmente gefahrlos proxy_ignore_headers Vary ergänzt werden (siehe 6.1).

8. Bereitstellung über ein CDN

Perfect Streamer ist mit einem CDN im Modus Pull-from-Origin kompatibel.

Origin shield. Es wird empfohlen, einen oder mehrere Shield-Knoten zwischen CDN-Edge und Origin zu platzieren, um die Anfragefrequenz am Origin bei globaler Verteilung der Clients zu senken.

Purge. Content-addressed Segmente erfordern keinen Purge. Bei Änderung der Metadaten des Streams (Codec, Auflösung) werden die Manifeste innerhalb von max-age=1 ohne expliziten Purge aktualisiert.

Cache warming. Bei erwartetem Lastanstieg auf einen bestimmten Stream ist ein Vorwärmen des CDN von mehreren geografischen Standorten aus vor Beginn der Übertragung zulässig.

Geografische Verteilung. Segmente (max-age=60) eignen sich gut für geografisch verteiltes Caching. Manifeste (max-age=1) lassen eine Auslieferungsverzögerung von bis zu einer Sekunde zu — für Live-Übertragungen ohne niedrige Latenz akzeptabel.

9. Überwachung

9.1. X-Cache-Status

Hinzufügen von add_header X-Cache-Status $upstream_cache_status; in jeder Location mit Caching. Werte:

Wert

Beschreibung

HIT

Antwort aus dem Cache

MISS

War nicht im Cache vorhanden, vom Origin bezogen und gespeichert

EXPIRED

Abgelaufen, aktualisiert

UPDATING

Während der Aktualisierung wurde einer parallelen Anfrage die Stale-Kopie geliefert

STALE

use_stale hat eine abgelaufene Kopie geliefert (Origin nicht erreichbar)

REVALIDATED

Der Origin hat 304 Not Modified zurückgegeben

BYPASS

proxy_cache_bypass hat ausgelöst

9.2. Format des Access-Logs

log_format pss_cache '$remote_addr $status $request_method "$request" '
                     '$body_bytes_sent rt=$request_time ut=$upstream_response_time '
                     'cache=$upstream_cache_status key=$pss_cache_key';

server {
    access_log /var/log/nginx/pss.log pss_cache;
}

9.3. Metriken

Das Modul nginx-vts exportiert Metriken pro Zone im Prometheus-Format:

GET /status/format/prometheus

Empfohlene Schwellenwerte für Alarme:

Metrik

Schwellenwert

Mögliche Ursache

Segment HIT rate

< 90% über 5 Minuten

Die Normalisierung des Cache Key ist verletzt; zu kleiner max_size

Manifest MISS rate

> 50% über 1 Minute

proxy_cache_lock serialisiert die Anfragen nicht

Upstream response time p95

> 500 ms über 1 Minute

Überlastung des Origin

Cache zone fill

> 90% über 10 Minuten

Annäherung an max_size, LRU-Eviction steht bevor

Die Auslieferungsqualität auf Knotenseite ist an den Sitzungsmetriken auf dem Bildschirm „Clients“ (Clients) ersichtlich.

10. Diagnose

Symptom

Wahrscheinliche Ursache

Lösung

Segment HIT rate niedrig

Vary: Origin teilt den Cache in Varianten auf; verletzte Normalisierung in map

proxy_ignore_headers Vary in der Location der Segmente ergänzen; Regex in der Direktive map prüfen

404 auf Segmenten nach dem Verlassen des Fensters

Gecachte 404 bei einem Segment, das aus dem Sliding Window herausgefallen ist

proxy_cache_valid 404 0s in der Location segments ergänzen

Verzögerung des Playback-Starts 2–5 s

proxy_cache_lock_timeout überschreitet die Target Latency

Auf 1–2 s senken; proxy_cache_use_stale updating aktivieren

Manifest wird nicht aktualisiert

proxy_ignore_headers Cache-Control ist gesetzt, und proxy_cache_valid mit großem TTL ist wirksam

proxy_cache_valid 200 1s explizit angeben oder das Ignorieren der Header entfernen

Anstieg von TIME_WAIT am Upstream

keepalive fehlt im Upstream-Block

keepalive 64, proxy_http_version 1.1, proxy_set_header Connection "" ergänzen

403 auf /dash/.../<segment>.m4s von Konsolen-Clients

Der Client löst relative URLs gegen die Pre-Redirect-URL auf

Der Server gibt <BaseURL> mit absolutem Pfad aus; im aktuellen Build kompatibel

Ruckler, häufiges Rebuffering bei entfernten Clients

Niedriger effektiver TCP-Durchsatz durch Slow Start und Idle Restart bei großen RTT (300 ms und mehr)

Tuning des Linux-Netzwerkstacks auf dem Origin: siehe 10.1

10.1. TCP-Tuning des Origin für High-RTT-Clients

Das Problem tritt bei Clients mit großem RTT zum Origin auf (zum Beispiel 300 ms und mehr), wenn die Bitrate des Streams nahe an der Kapazität des Kanals liegt. Symptome im Player sind häufiges Rebuffering und Abbrüche; auf dem Server wirkt der Client dabei normal, Fehler treten nicht auf.

Ursache:

  • TCP slow start. Jede neue TCP-Verbindung beginnt mit einem Congestion Window von etwa 14 KB und vergrößert es über mehrere RTT. Bei einem RTT von 300 ms dauert das Erreichen des vollen Fensters 2–3 Sekunden. In dieser Zeit wird ein HLS/DASH-Segment von 5 s Dauer (4–6 MB) merklich langsamer als in Echtzeit heruntergeladen.

  • TCP idle restart. Zwischen den Segmentanfragen legt der Client im HLS-Pull-Modell eine Pause von 4–5 s ein. Standardmäßig setzt der Linux-Kernel nach einer solchen Pause das Congestion Window der Verbindung auf das Initial cwnd zurück (Verhalten net.ipv4.tcp_slow_start_after_idle=1). Dadurch beginnt die Keep-alive-Verbindung beim nächsten GET die Übertragung erneut mit Slow Start — selbst in einer bereits eingelaufenen Sitzung.

Erschwerend kommt hinzu, dass das standardmäßige Congestion Control CUBIC lange RTT und Paketverluste auf zwischengeschalteten Netzabschnitten schlecht verkraftet.

Die Lösung sind zwei sysctl-Parameter auf dem Origin:

# Keep congestion window across idle pauses inside keep-alive sessions.
sysctl -w net.ipv4.tcp_slow_start_after_idle=0

# Use BBR instead of CUBIC: better behaviour on long-RTT paths
# with mild packet loss; paces sending instead of bursting.
modprobe tcp_bbr
sysctl -w net.ipv4.tcp_congestion_control=bbr

Für die dauerhafte Anwendung:

cat > /etc/sysctl.d/99-pss-net.conf <<EOF
net.ipv4.tcp_slow_start_after_idle = 0
net.ipv4.tcp_congestion_control    = bbr
EOF
sysctl --system

Die Hauptwirkung erzielt der erste Parameter (tcp_slow_start_after_idle=0) — er beseitigt unmittelbar den erneuten Slow Start zwischen den Segmentanfragen innerhalb derselben Keep-alive-Verbindung. Der zweite (BBR) bringt zusätzliche Stabilität und gilt für alle neuen Verbindungen. Das Tuning erfordert keinen Neustart von Perfect Streamer. Für HTTP/3-Clients (QUIC) gelten diese Parameter nicht: QUIC arbeitet über UDP mit eigener Überlastungssteuerung.

11. Sicherheit

11.1. Session URL

Eine URL im Format /h<sess>/... erfüllt die Funktion eines Sitzungstokens — sie erfordert keine erneute Authentifizierung. Die Lebensdauer ist durch ein Inaktivitäts-Timeout von 60 Sekunden begrenzt; bleibt Aktivität aus, wird die Sitzung automatisch gelöscht.

Anforderungen:

  • HTTPS für alle OTT-Pfade (/hls/, /dash/, /h<sess>/) im Produktivbetrieb;

  • Die Session ID im Header Location der 302-Antwort wird nicht gecacht (no-cache, no-store).

11.2. Rate limiting

limit_req_zone $binary_remote_addr zone=dash_top:10m  rate=5r/s;
limit_req_zone $binary_remote_addr zone=hls_top:10m   rate=5r/s;
limit_req_zone $binary_remote_addr zone=llhls_top:10m rate=5r/s;

server {
    location /dash/ {
        limit_req zone=dash_top burst=20 nodelay;
        proxy_pass http://pss_backend;
    }
    location /hls/ {
        limit_req zone=hls_top burst=20 nodelay;
        proxy_pass http://pss_backend;
    }
    location /llhls/ {
        limit_req zone=llhls_top burst=20 nodelay;
        proxy_pass http://pss_backend;
    }
}

Die Session-URL (/h<sess>/) erfordert kein Rate Limiting — die Verarbeitung ist günstig, die Antworten werden gecacht.

11.3. Caching von Fehlerantworten

proxy_cache_valid 200 60s;
proxy_cache_valid 301 302 0s;
proxy_cache_valid 404 403 0s;
proxy_cache_valid any 1s;

Verbietet das Caching von Redirects (eindeutige sess in Location) sowie von Antworten mit Autorisierungsfehlern oder fehlender Ressource.

11.4. Beschränkung des Netzwerkzugriffs auf den Origin

Der Port des Streaming-HTTP-Servers (standardmäßig 43972; 43982 für HTTPS) muss für externen Verkehr gesperrt sein. Zulässige Konfigurationen:

  1. Perfect Streamer an 127.0.0.1 binden (bei lokalem nginx)

  2. Firewall-Regel:

iptables -A INPUT -p tcp -m multiport --dports 43972,43982 ! -s 10.0.0.0/8 -j DROP

12. Integration mit Middleware

12.1. Modell prefix-login

Perfect Streamer unterstützt die Delegierung der Benutzeridentifikation an ein Middleware-System über den Mechanismus prefix-login — eine eingebaute Alternative zur vollständigen Integration mit einem externen Billing-System (Konten, die von einem externen System geprüft werden, werden auf dem Bildschirm „Benutzer / Logins“ auf der Registerkarte „Extern (Billing)“ konfiguriert, Benutzer / Logins).

Beim lokalen Login wird das Präfix-Merkmal aktiviert, woraufhin der Server URLs mit einem Login der Form <prefix><Abonnenten-ID> akzeptiert:

/dash/test1/sub42/xxx/index.mpd
/hls/test1/sub43/xxx/index.m3u8

Hier ist sub das konfigurierte Login-Präfix, und 42/43 sind die Abonnentenbezeichner der Middleware; das Passwort ist gemeinsam.

12.2. Statistik nach Abonnenten

In der Liste der Clients trägt jede Sitzung sowohl den konfigurierten Login als auch den tatsächlichen URL-Login des Abonnenten (match-login), über den die Middleware die Sitzungen ihren eigenen Teilnehmern zuordnet. Die Daten sind auf dem Bildschirm „Clients“ (Clients) sichtbar.

12.3. Einschränkungen von prefix-login

  • Gemeinsames Passwort. Alle Abonnenten eines prefix-Pools verwenden denselben Passwortwert. Eine Kompromittierung des Passworts gewährt Zugriff auf jedes <prefix><Zeichenfolge>.

  • Zugriffsgranularität. Die Liste der erlaubten Streams gilt für den gesamten prefix-Pool. Zugriff auf der Ebene einzelner Abonnenten bietet die Integration mit einem externen Billing-System.

  • Passwortrotation. Eine Änderung des Passworts trennt alle aktiven Abonnenten. Für einen schrittweisen Wechsel ist die vorübergehende Nutzung zweier prefix-Logins erforderlich.