Cascade SFU: Verbesserung der Skalierbarkeit und Qualität von Medien in WebRTC-Anwendungen

Published on December 11, 2018

Cascade SFU: Verbesserung der Skalierbarkeit und Qualität von Medien in WebRTC-Anwendungen

Ursprünglicher Autor: Boris Grozev
  • Übersetzung
Es gibt zwei Schwierigkeiten beim Bereitstellen von Medienservern für WebRTC: Skalierung, d. H. Sie müssen nicht mehr nur einen Server verwenden und die Verzögerungen für alle Konferenzteilnehmer optimieren. Während einfaches Sharding im Sinne von "Alle Benutzer von Konferenz X an Server Y senden" leicht horizontal skaliert werden kann, ist es in Bezug auf Verzögerungen bei weitem nicht optimal. Das Verteilen einer Konferenz an Server, die nicht nur nahe am Benutzer, sondern auch miteinander verbunden sind, scheint eine Lösung für beide Probleme zu sein. Heute haben wir eine Übersetzung des detaillierten Materials von Boris Grosev aus Jitsi vorbereitet: Probleme bei der Kaskadierung von SFUs, mit einer Beschreibung des Ansatzes und einiger Schwierigkeiten sowie Einzelheiten der Implementierung. Es ist erwähnenswert, dass Voximplant-Konferenzen auch SFU verwenden; Wir arbeiten derzeit an der SFU-Kaskadierung, die nächstes Jahr auf unserer Plattform erscheinen soll.


Maus-Neuronen. Image NIHD ( CC-BY-2.0 )

Echtzeitkommunikation reagiert sehr empfindlich auf das Netzwerk: Bandbreite, Latenz und Paketverlust. Das Verringern der Bitrate führt zu einer geringeren Videoqualität, eine lange Netzwerkverzögerung führt zu einer langen Verzögerung für Endbenutzer. Der Verlust von Paketen kann den Ton zeitweilig machen und zu Friesen im Video führen (aufgrund von fehlenden Frames).

Daher ist es für die Konferenz sehr wichtig, den besten Weg zwischen den Endgeräten / Benutzern zu wählen. Wenn nur zwei Benutzer vorhanden sind, ist es einfach - WebRTC verwendet das ICE-Protokolleine Verbindung zwischen den Teilnehmern herzustellen. Wenn möglich, werden die Teilnehmer direkt verbunden, andernfalls wird der TURN-Server verwendet. WebRTC kann den Domain-Namen erneut auflösen, um die Adresse des TURN-Servers abzurufen, sodass Sie auf einfache Weise eine lokale TURN auf DNS-Basis auswählen können, indem Sie beispielsweise die Eigenschaften von AWS Route53 verwenden .

Wenn jedoch die Weiterleitung mehrerer Teilnehmer über einen zentralen Medienserver erfolgt, wird die Situation kompliziert. Viele WebRTC-Dienste verwenden selektive Weiterleitungseinheiten (SFU), um Audio und Video effizienter zwischen drei oder mehr Teilnehmern zu übertragen.

Sternproblem


In der Sterntopologie stellen alle Teilnehmer eine Verbindung zu einem Server her, über den sie Medienströme austauschen. Offensichtlich ist die Wahl des Serverstandorts von großer Bedeutung: Wenn sich alle Teilnehmer in den USA befinden, ist die Verwendung eines Servers in Sydney nicht die beste Idee.


Viele Dienste verwenden einen einfachen Ansatz, der in den meisten Fällen gut funktioniert: Sie wählen einen Server, der näher am ersten Konferenzteilnehmer liegt. Es gibt jedoch Zeiten, in denen diese Lösung nicht optimal ist. Stellen Sie sich vor, wir haben drei Teilnehmer aus dem obigen Bild. Wenn der Australier (Anrufer C) als erster eine Verbindung zur Konferenz herstellt, wählt der Algorithmus einen Server in Australien aus, Server 1 in den USA ist jedoch die beste Wahl, da Er ist den meisten Teilnehmern näher.

Das beschriebene Szenario ist nicht sehr häufig, aber es tut es. Wenn wir annehmen, dass ein Benutzer in zufälliger Reihenfolge verbunden ist, tritt die beschriebene Situation bei with aller Konferenzen mit 3 Teilnehmern auf, von denen einer stark entfernt ist.

Ein weiteres und häufigeres Szenario: Wir haben zwei Teilnehmergruppen an verschiedenen Standorten. In diesem Fall ist die Reihenfolge der Verbindung unwichtig. Wir haben immer eine Gruppe von Teilnehmern in der Nähe, die gezwungen sind, Medien mit einem Remote-Server auszutauschen. Zum Beispiel 2 Teilnehmer aus Australien (C & D) und 2 aus den USA (A & B).


Der Wechsel zu Server 1 ist für C & D-Mitglieder nicht optimal. Server 2 ist für A & B nicht optimal. Das heißt, unabhängig davon, welcher Server verwendet wird, sind immer Teilnehmer mit einem entfernten (= nicht optimalen) Server verbunden.

Hätten wir aber keine Einschränkungen auf einem Server? Wir könnten jeden Teilnehmer mit dem nächsten Server verbinden, es wäre nur nötig, diese Server zu verbinden.

Lösung: Kaskadieren


Lassen Sie uns die Frage nach der Verbindung der Server verschieben. Mal sehen, was der Effekt sein wird.


Die SFU-Verbindung zwischen C und D hat sich nicht geändert - Server 2 wird weiterhin verwendet. Für Teilnehmer A und B wird Server 1 verwendet, und dies ist offensichtlich besser. Das Interessanteste ist die Verbindung zwischen beispielsweise A und C: Anstelle von A <=> Server 2 <=> C wird die Route A <=> Server 1 <=> Server 2 <=> C verwendet.

Implizite Auswirkung auf den Wechselkurs


Der SFU-Mix hat Vor- und Nachteile. Einerseits wird in der beschriebenen Situation die Austauschzeit zwischen den Teilnehmern durch Hinzufügen neuer Sprünge über das Netzwerk länger. Auf der anderen Seite gibt es eine Verkürzung dieser Zeit, wenn wir über die Verbindung „Client“ - „der erste Server“ sprechen, weil wir den Medienstrom mit weniger Verzögerung nach dem Hop-by-Hop-Prinzip wiederherstellen können.

Wie funktioniert es WebRTC verwendet RTP (normalerweise über UDP) zum Übertragen von Medien. Dies bedeutet, dass der Transport unzuverlässig ist. Wenn ein UDP-Paket verloren geht, können Sie den Verlust ignorieren oder eine erneute Übertragung (Retransmission) mithilfe des RTCP-NACK- Pakets anfordern- Die Wahl liegt bereits im Gewissen des Antrags. Beispielsweise kann eine Anwendung den Verlust von Audiopaketen ignorieren und die erneute Übertragung einiger (aber nicht aller) Videopakete anfordern, je nachdem, ob sie zum Decodieren nachfolgender Frames benötigt werden oder nicht.


RTP-Paket-Neuübertragung, einzelner Server

Wenn eine Kaskade vorliegt, kann die Neuübertragung auf den lokalen Server beschränkt werden, dh, sie kann an jedem bestimmten Standort ausgeführt werden. Wenn zum Beispiel in der Route A-S1-S2-C das Paket zwischen A und S1 verloren geht, wird S1 eine erneute Übertragung bemerken und anfordern; in ähnlicher Weise mit einem Verlust zwischen S2 und C. Und selbst wenn das Paket zwischen Servern verloren geht, kann der empfangende Teilnehmer auch eine erneute Übertragung anfordern.


RTP-Paket-Neuübertragung, zwei Server. Beachten Sie, dass Server 2 Paket 2 nicht anfordert, da der NACK kurz nach dem Senden des Pakets angekommen ist.

Auf dem Client wird der Jitter-Puffer verwendet, um die Videowiedergabe zu verzögern und Zeit zum Empfangen verzögerter / erneuter Sendepakete zu haben. Die Puffergröße ändert sich dynamisch in Abhängigkeit von der Austauschzeit zwischen den Parteien. Wenn Hop-by-Hop-Neuübertragungen auftreten, verringert sich die Verzögerung, und infolgedessen kann der Puffer geringer sein - infolgedessen verringert sich auch die Gesamtverzögerung.

Kurz gesagt: Auch wenn die Austauschzeit zwischen den Teilnehmern länger ist, kann dies die Verzögerung bei der Übertragung von Medien zwischen den Teilnehmern verringern. Diesen Effekt müssen wir in der Praxis erst noch untersuchen.

Einführung von Cascading SFU: Jitsi Meet Case


Alarm vs. Medien


Werfen wir einen Blick auf den Alarm. Von Anfang an teilte Jitsi Meet das Konzept des Alarmservers ( Jicofo ) und des Medienservers / SFU. Dies ermöglichte eine relativ einfache Kaskadenunterstützung. Erstens könnten wir die gesamte Alarmlogik an einem Ort abwickeln. Zweitens hatten wir bereits ein Signalisierungsprotokoll zwischen Jicofo und dem Medienserver. Wir mussten die Funktionalität nur ein wenig erweitern: Wir hatten bereits mehrere SFUs mit einem Alarmserver verbunden, wir mussten die Fähigkeit einer SFU hinzufügen, sich mit mehreren Alarmservern zu verbinden.

Infolgedessen wurden zwei unabhängige Serverpools angezeigt: einer für jicofo-Instanzen und der andere für Medienserverinstanzen (siehe Abbildung):


Ein Beispiel für die Organisation von Servern in AWS mit der Möglichkeit einer Kaskade zwischen verschiedenen Rechenzentren.

Der zweite Teil des Systems ist die Bridge-to-Bridge-Verbindung. Wir wollten diesen Teil so einfach wie möglich gestalten, damit es keine komplexen Signale zwischen den Brücken gibt. Alle Alarme werden zwischen jicofo und jitsi-videobridge ausgegeben. Die Verbindung zwischen Bridges wird nur für Audio- / Video- und Datenkanalnachrichten verwendet.

Octo-Protokoll


Um diese Interaktion zu verwalten, haben wir das Octo-Protokoll verwendet, das RTP-Pakete in einfache Header mit fester Länge umschließt und das Senden einer Textnachricht ermöglicht. In der aktuellen Implementierung sind die Brücken in einer Vollmaschentopologie (Full Mesh) verbunden, andere Topologen sind jedoch möglich. Verwenden Sie beispielsweise einen zentralen Server (ein Stern für Brücken) oder eine Baumstruktur für jede Brücke.

Erläuterung: Anstatt einen Octo-Header einzuschließen, können Sie die RTP-Header-Erweiterung verwenden, mit der der Fluss zwischen Bridges auf reinem (S) RTP hergestellt wird. Zukünftige Versionen von Octo können diesen Ansatz verwenden.

Zweite Erklärung: Octo bedeutet nichts. Zuerst wollten wir einen zentralen Server verwenden, was uns an einen Tintenfisch erinnerte. So erschien der Name für das Projekt.

Octo-Header-Format

Wenn in der Jitsi-Terminologie eine Bridge Teil einer Konferenz mit mehreren Bridges ist, verfügt sie über einen zusätzlichen Octo-Kanal (in der Tat einen Kanal für Audio und einen für Video). Dieser Kanal ist für das Senden / Empfangen von Medien zu / von anderen Bridges verantwortlich. Jeder Bridge ist ein freier Port für Octo zugewiesen (standardmäßig 4096). Daher benötigen wir das Feld Konferenz-ID, um mehrere Konferenzen abzuwickeln.

Im Moment verfügt das Protokoll über keine integrierten Sicherheitsmechanismen und wir delegieren diese Verantwortung an die unteren Ebenen. Dies ist das Nächste, was wir in naher Zukunft tun werden. Derzeit sollten sich die Bridges jedoch in einem sicheren Netzwerk befinden (z. B. in einer separaten AWS VPC-Instanz).

Simulcast


Simulcast ermöglicht es jedem Teilnehmer, mehrere Medienströme mit unterschiedlichen Bitraten zu senden, während die Bridge dabei hilft, zu bestimmen, welche benötigt werden. Damit dies korrekt funktioniert, übertragen wir alle Simulcast-Streams zwischen Bridges. Auf diese Weise können Sie schnell zwischen Threads wechseln, da die lokale Bridge keinen neuen Stream anfordern sollte. Dies ist jedoch aus Sicht des Bridge-to-Bridge-Verkehrs nicht optimal, da Einige Streams werden selten verwendet und laden nur die Bandbreite ohne Zweck.

Auswahl des aktiven Teilnehmers


Wir wollten auch die Möglichkeit, den aktiven Teilnehmer / Sprecher der Konferenz zu abonnieren. Es stellte sich als einfach heraus - wir brachten jeder Brücke bei, den Hauptteilnehmer unabhängig zu bestimmen und dann ihre lokalen Kunden zu benachrichtigen. Dies bedeutet, dass die Definition mehrmals erfolgt, aber nicht teuer ist und Sie einige Punkte vereinfachen können (z. B. müssen Sie nicht entscheiden, welche Bridge für DSI verantwortlich sein soll, und sich keine Gedanken über das Weiterleiten von Nachrichten machen).

Brückenauswahl


In der aktuellen Implementierung ist dieser Algorithmus einfach. Wenn ein neuer Teilnehmer an der Konferenz teilnimmt, muss Jicofo bestimmen, welche Bridge ihm zugewiesen werden soll. Dies erfolgt basierend auf der Region des Teilnehmers und der Auslastung der Brücken. Wenn es in derselben Region eine freie Brücke gibt, wird sie ernannt. Andernfalls wird eine andere Brücke verwendet.

Details zu Octo finden Sie in der Dokumentation .

Erweitern Sie die Kaskaden-SFU


Für die Bereitstellung verwendeten wir Amazon AWS-Maschinen. Wir hatten Server (Signalisierung und Medien) in 6 Regionen:

  • us-east-1 (Nord-Virginia);
  • us-west-2 (Oregon);
  • eu-west-1 (Irland);
  • eu-central-1 (Frankfurt);
  • ap-se-1 (Singapur);
  • ap-se-2 (Sydney).

Wir haben georeferenzierte HAProxy- Instanzen verwendet , um die Region des Teilnehmers zu bestimmen. Die Domäne "meet.jit.si" wird von Route53 verwaltet und in die HAProxy-Instanz aufgelöst, die den HTTP-Anforderungsheadern die Region hinzufügt. Der Header wird später als Wert einer Variablen verwendet config.deploymentInfo.userRegion, die auf dem Client über die Datei verfügbar ist /config.js.

Die Jitsi-Oberfläche zeigt, wie viele Bridges verwendet werden und an welche bestimmten Benutzer sie angeschlossen sind - zu Diagnose- und Demonstrationszwecken. Wenn Sie den Mauszeiger über die linke obere Ecke des lokalen Videos bewegen, werden die Gesamtzahl der Server und der Server angezeigt, mit dem Sie verbunden sind. Ebenso können Sie die Parameter des zweiten Teilnehmers sehen. Außerdem sehen Sie die Austauschzeit zwischen Ihrem Browser und dem Browser des anderen Teilnehmers (Parameter E2E RTT).


Wenn Sie sich ansehen, wer mit welchem ​​Server verbunden ist, können Sie feststellen, ob die Kaskadierung verwendet wird.

Fazit


Octo erschien ursprünglich als A / B-Test. Die ersten Ergebnisse waren gut, sodass Octo nun für alle verfügbar ist. Sie müssen viel Verkehr durchlaufen und die Leistung genauer untersuchen. Es ist auch geplant, diese Entwicklungen zu nutzen, um noch größere Konferenzen zu unterstützen (wenn eine SFU nicht mehr ausreicht).