Video-Prefetching mit Compute
Nichts ist ärgerlicher, als sich eine heiß ersehnte Sendung mit ständig zeitlich verzögerten Bildern anschauen zu müssen. Daher sollten Publisher Video-Prefetching in Betracht ziehen, um das Zuschauererlebnis für ihre Abonnenten so angenehm wie nur möglich zu gestalten.
Warum den Cache vorwärmen?
Bei Videoinhalten, die schon eine geraume Zeit nicht mehr aufgerufen wurden, sowie bei neuen Videoinhalten dauert die TTFB (Time to First Byte) wesentlich länger, wenn die Anfrage für jedes Videoschnipsel bis ganz zurück an den Origin geschickt werden muss. Kann ein Publisher davon ausgehen, dass zu einer bestimmten Uhrzeit die Zuschauer besonders zahlreich sein werden, ist es ideal, wenn sämtliche Videoobjekte bereits im Edge-Cache vorliegen. Denn dann können die Videoinhalte sehr schnell an die verschiedenen geografischen Regionen ausgeliefert werden.
Nehmen wir die letzte Folge von „Game of Thrones“ des Kabelsenders HBO als Beispiel: Diese Fernsehserie war äußerst beliebt, und Millionen von Fans warteten aufgeregt auf den Sendetermin: Sonntagabend 20:00 Uhr. Bei HBO war klar, dass ein riesiges, geografisch verstreutes Publikum genau um 20:00 Uhr auf „Play“ drücken wird. Da es sich bei diesem Video um nie gezeigte Inhalte handelte, wäre ohne ein Vorwärmen des Cache ein Cache Miss vorprogrammiert – alle Zuschaueranfragen würden an den Ursprungsserver weitergeleitet. Das wiederum würde zu langen Bufferzeiten, verringerter Performance und letztlich verärgerten Zuschauern führen.
Zur Vermeidung dieses Problems hat HBO ein Prefetching sämtlicher Videoobjekte oder zumindest der ersten paar Sekunden des Videos vorgenommen, sodass das Video ohne Verzögerung abgespielt werden konnte.
Häufige Problempunkte beim Vorwärmen
Traditionell erfolgte ein Cache-Vorwärmen entweder durch Anmelden an den einzelnen Cache-Nodes und Ausführen eines Skripts zum Abrufen sämtlicher Videoobjekte oder durch Einrichten jeweils eines Clients in den einzelnen geografischen Regionen über ein VPN und Anfragen der Videoobjekte von diesen Clients. Dieser Ansatz birgt jedoch einige Probleme:
Das Verfahren ist langsam und nur schwer zu beherrschen. Man benötigt eine Menge interner Netzwerkinformationen über das CDN, mit dem man arbeitet. Zudem muss man wissen, wie man auf die einzelnen POPs zugreift. Bei einer Realisierung anhand von Clients muss man für jede einzelne geografische Region wissen, wie das Routing zu den einzelnen POPs abläuft.
Möglicherweise verschwendet man wertvolle Cache-Ressourcen des CDN für Inhalte, die sich niemand jemals anschauen wird. Wenn man z. B. sämtliche POPs weltweit vorgewärmt hat, die betreffenden Inhalte jedoch ausschließlich in Nordamerika konsumiert werden, enthalten alle anderen POPs Videoobjekte, die niemals an auch nur einen einzigen Abonnenten weitergegeben wurden.
Vorwärmen mit Compute
Vor Compute waren unsere Möglichkeiten zum Bedienen einer Anfrage doch recht eingeschränkt. VCL hat keine Möglichkeit zum Manipulieren des Anfrage-/Antwort-Body. Zudem verfügt VCL über nur eingeschränkte Mittel zum Bearbeiten von asynchronen Anfragen.
Compute beseitigt all diese Einschränkungen und gibt uns hochinteressante Mittel für das Bereitstellen von Videos an die Hand, darunter auch effizientes Prefetching/Cache-Aufwärmen.
Manifest-Anfrage im Voraus
Zunächst eine kurze Erläuterung zur Bereitstellung von Videos als Stream:
Videoinhalte werden Schritt für Schritt und stückchenweise bereitgestellt. Ein clientseitiger Player fragt eine Datei an. Diese Datei heißt „Manifest“ und enthält URLs zu anderen Videoobjekten, die der Player abruft, sobald er sie für das Buffering oder die Wiedergabe benötigt.
Hier sehen Sie einen Ausschnitt aus einem solchen Playlist-Manifest zu einer 720-p-Version von „Big Buck Bunny“. Der Ausschnitt enthält die ersten drei relevanten URLs (die Einträge mit der Erweiterung „.ts“).
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-ALLOW-CACHE:YES
#EXT-X-TARGETDURATION:13
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:12.500000,
buck_720p_0000.ts
#EXTINF:7.666667,
buck_720p_0001.ts
#EXTINF:11.466667,
buck_720p_0002.ts
#EXTINF:12.300000,
buck_720p_0003.ts
Der Player ruft jedes dieser Mediensegmente der Reihe nach ab. Bei einer herkömmlichen Vorgehensweise, ohne Prefetching, würde die Anfrage bei „kaltem Cache“ für jedes einzelne Segment den gesamten Weg zurück zum Ursprungsserver zurücklegen. Das kann besser gelöst werden!
Wie bereits erwähnt, kann Compute den Body der Anfrage lesen. Daher können wir eine simple Anwendung zum Vorwärmen des Cache schreiben und auf der Edge ausführen. Bei Abruf des Manifests durch den Player kann die Anfrage an den Origin weitergeleitet werden – jedoch parst der Player die eintreffende Antwort und extrahiert die ersten n URLs zu den Medienobjekten. Anschließend kann das Manifest wieder an den Client zurückgegeben werden. Das folgende Code-Snippet veranschaulicht genau das:
match m3u8_rs::parse_playlist_res(new_resp.take_body_bytes().as_slice()) {
Ok(Playlist::MasterPlaylist(_pl)) => println!("Master playlist"),
Ok(Playlist::MediaPlaylist(pl)) => {
println!("Media Playlist. Path = {}", path_str);
send_media_segments_requests_async(&pl, req_url)?;
}
Err(_e) => fastly::error::bail!("Invalid manifest"),
}
// I got what I needed so return the beresp in a Result
Ok(beresp)
}
Der Player findet die ersten n Mediensegmente und sendet die Anfragen asynchron. Die Antworten werden ignoriert. Das geht sehr schnell. Also senden wir das Manifest nahezu ohne Verzögerung zurück an den Player. Die Antworten auf die Anfragen zu den Mediensegmenten interessieren uns nicht weiter. Schließlich wollten wir die Segmente ja nur in den CDN-Cache abrufen. Wenn der Player später diese Mediensegmente anfragt, sollten sich diese Segmente bereits im Cache befinden.
CMCD-NOR
Einer der Standards, an dem die Consumer Technology Association (CTA) arbeitet, nennt sich „Common Media Client Data“ (CMCD). CMCD ist eine offene Spezifikation, in der ergänzende Informationen zur Unterstützung von Analyse, Monitoring und Optimierung der Bereitstellung von Streaminginhalten definiert sind. Diese Tools erhöhen die Transparenz bezüglich QoS und können helfen, die Bereitstellungsperformance zu steigern. In einem nächsten Blogpost werden wir genauer auf CMCD eingehen.
Eines der Elemente von CMCD ist der „Next Object Request“ (NOR). Dabei handelt es sich um einen String, der entweder als Abfrageparameter oder in einem Header übergeben werden kann und der die nächste URL des nächsten anzufragenden Objekts repräsentiert. Diese Compute Anwendung funktioniert ähnlich wie die Anwendung weiter oben. Anstatt jedoch im Manifest nach dem nächsten Objekt zu suchen, durchsuchen wir die Abfrage bzw. die Header:
match req.get_header("cmcd-request") {
Some(cmcd) => {
let cmcd = cmcd.to_str().unwrap().to_string();
send_nor_request(cmcd, &req);
}
None => {
// We looked for a cmcd-request header and it wasn't there so let's see if it's in the
// query parameters.
if let Ok(q) = req.get_query() {
let qs_map: HashMap<String, String> = q;
if qs_map.contains_key("CMCD") {
let cmd = qs_map.get("CMCD").unwrap();
send_nor_request(cmd.to_string(), &req);
}
};
}
}
Hier suchen wir nach der NOR-Anfrage in den Headern und, falls dort nicht vorhanden, überprüfen die Abfrageparameter. Haben wir die NOR-Anfrage gefunden, übergeben wir sie an die Funktion „send_nor_request“. Diese Funktion filtert die NOR-URL heraus und sendet anschließend die Anfrage asynchron.
Next Generation Intelligence
Die oben aufgeführten Workflows sind einleuchtend und einfach in die Produktivumgebung zu überführen. Die Vielseitigkeit und Leistungsstärke von Compute eröffnet uns jedoch zahlreiche weitere Möglichkeiten. Im Folgenden sind einige Überlegungen aufgeführt, die auf Compute aufgebaut werden könnten:
Ein Prefetching des Nachspanns lohnt sich nicht: Gegen Ende des Videos nimmt die Zuschauerschaft ab, die wenigsten sehen sich den Nachspann an. Auf das Prefetching von Nachspännen kann also gut und gerne verzichtet werden. Sie könnten die Anwendung um eine Funktion zum Erkennen des Beginns des Nachspanns erweitern, beispielsweise anhand eines bestimmten Zeitstempels, eines bestimmten Tags oder sonstiger Metadaten, und das Prefetching dann an dieser Stelle stoppen.
Intelligentes Prefetching auf der Basis von Nutzungsmustern: Sie könnten das Prefetching mithilfe von KI/ML weiter optimieren. So könnten Sie z. B. mithilfe von KI ermitteln, zu welchen Uhrzeiten ein bestimmtes Video besonders beliebt ist, und den Cache dann nur zu diesen Zeiten vorwärmen.
Zusammenfassung
Beim „Vorwärmen“ des Cache mittels Compute steht Ihnen nicht nur ein leistungsstarkes, weltweit verteiltes Netzwerk zur Verfügung, Sie vermeiden gleichzeitig auch die Problempunkte früherer Verfahren für das Prefetching.