Wie passen Streaming-Ressourcen in das RESTful-Paradigma?


101

Mit einem RESTful-Service können Sie Ressourcen erstellen, lesen, aktualisieren und löschen. Dies alles funktioniert gut, wenn Sie mit so etwas wie Datenbank-Assets arbeiten - aber wie wird dies in Streaming-Daten übersetzt? (Oder doch?) Im Fall von Video erscheint es beispielsweise albern, jeden Frame als Ressource zu behandeln, die ich einzeln abfragen sollte. Vielmehr würde ich eine Socket-Verbindung einrichten und eine Reihe von Frames streamen. Aber bricht dies das RESTful-Paradigma? Was ist, wenn ich den Stream zurückspulen oder vorspulen möchte? Ist dies innerhalb des RESTful-Paradigmas möglich? Also: Wie passen Streaming-Ressourcen in das RESTful-Paradigma?

Bei der Implementierung bereite ich mich darauf vor, einen solchen Streaming-Datendienst zu erstellen, und ich möchte sicherstellen, dass ich es auf die "beste Art und Weise" mache. Ich bin sicher, dass dieses Problem schon einmal gelöst wurde. Kann mich jemand auf gutes Material hinweisen?


2
Welche Option haben Sie letztendlich gewählt? Hast du dir gRPc angesehen? Es unterstützt bidirektionales Streaming.
Mac

Antworten:


80

Ich habe es nicht geschafft, Materialien über wirklich RESTful-Streaming zu finden - es scheint, dass es bei den Ergebnissen hauptsächlich darum geht, Streaming an einen anderen Dienst zu delegieren (was keine schlechte Lösung ist). Also werde ich mein Bestes tun, um es selbst anzugehen - beachten Sie, dass Streaming nicht meine Domain ist, aber ich werde versuchen, meine 2 Cent hinzuzufügen.

In Bezug auf das Streaming denke ich, dass wir das Problem in zwei unabhängige Teile aufteilen müssen:

  1. Zugriff auf Medienressourcen (Metadaten)
  2. Zugriff auf das Medium / den Stream selbst (Binärdaten)

1.) Zugriff auf Medienressourcen
Dies ist ziemlich unkompliziert und kann auf saubere und ruhige Weise gehandhabt werden. Nehmen wir als Beispiel an, wir haben eine XML-basierte API, mit der wir auf eine Liste von Streams zugreifen können:

GET /media/

<?xml version="1.0" encoding="UTF-8" ?>
<media-list uri="/media">
    <media uri="/media/1" />
    <media uri="/media/2" />
    ...
</media-list>

... und auch zu einzelnen Streams:

GET /media/1

<?xml version="1.0" encoding="UTF-8" ?>
<media uri="/media/1">
    <id>1</id>
    <title>Some video</title>
    <stream>rtsp://example.com/media/1.3gp</stream>
</media>

2.) Zugriff auf das Medium / den Stream selbst
Dies ist das problematischere Bit. Sie haben in Ihrer Frage bereits auf eine Option hingewiesen, nämlich den Zugriff auf Frames einzeln über eine RESTful-API. Auch wenn dies funktionieren könnte, stimme ich Ihnen zu, dass dies keine praktikable Option ist.

Ich denke, dass es eine Wahl gibt zwischen:

  1. Delegieren von Streaming an einen dedizierten Dienst über ein spezielles Streaming-Protokoll (z. B. RTSP)
  2. Verwenden der in HTTP verfügbaren Optionen

Ich glaube, Ersteres ist die effizientere Wahl, obwohl es einen dedizierten Streaming-Dienst (und / oder Hardware) erfordert . Es könnte etwas am Rande dessen liegen, was als RESTful angesehen wird. Beachten Sie jedoch, dass unsere API in allen Aspekten RESTful ist und obwohl der dedizierte Streaming-Dienst nicht der einheitlichen Schnittstelle (GET / POST / PUT / DELETE), unserer API, entspricht tut. Unsere API ermöglicht uns die ordnungsgemäße Kontrolle über Ressourcen und deren Metadaten über GET / POST / PUT / DELETE, und wir stellen Links zum Streaming-Service bereit (wobei der Verbindungsaspekt von REST eingehalten wird).

Die letztere Option - Streaming über HTTP - ist möglicherweise nicht so effizient wie die oben genannte, aber definitiv möglich. Technisch gesehen ist es nicht anders, als den Zugriff auf jede Form von binären Inhalten über HTTP zuzulassen. In diesem Fall würde unsere API einen Link zu der über HTTP zugänglichen binären Ressource bereitstellen und uns auch über die Größe der Ressource informieren:

GET /media/1

<?xml version="1.0" encoding="UTF-8" ?>
<media uri="/media/1">
    <id>1</id>
    <title>Some video</title>
    <bytes>1048576</bytes>
    <stream>/media/1.3gp</stream>
</media>

Der Client kann über HTTP mithilfe von auf die Ressource zugreifen GET /media/1.3gp. Eine Möglichkeit besteht darin, dass der Client die gesamte Ressource herunterlädt - den progressiven HTTP-Download . Eine sauberere Alternative wäre, dass der Client mithilfe von HTTP- Bereichskopfzeilen in Blöcken auf die Ressource zugreift . Zum Abrufen des zweiten 256-KB-Blocks einer 1 MB großen Datei sieht die Clientanforderung dann folgendermaßen aus:

GET /media/1.3gp
...
Range: bytes=131072-262143
...

Ein Server, der Bereiche unterstützt, antwortet dann mit dem Content-Range-Header , gefolgt von der teilweisen Darstellung der Ressource:

HTTP/1.1 206 Partial content
...
Content-Range: bytes 131072-262143/1048576
Content-Length: 1048576
...

Beachten Sie, dass unsere API dem Client bereits die genaue Größe der Datei in Byte (1 MB) mitgeteilt hat. In einem Fall, in dem der Client die Größe der Ressource nicht kennt, sollte er zuerst aufrufen HEAD /media/1.3gp, um die Größe zu bestimmen, da sonst eine Serverantwort mit riskiert wird 416 Requested Range Not Satisfiable.


2
Wow ... das sind großartige Informationen. Sie haben mich auf einige neue Denkweisen aufmerksam gemacht. Das Real Time Streaming Protocol war mir auch nicht bekannt.
JnBrymn

1
Kein Problem, ich bin froh, dass ich helfen konnte. Bitte beachten Sie jedoch, dass ich noch keine Möglichkeit hatte, persönlich mit Streaming-Protokollen zu arbeiten (mit Ausnahme des progressiven Streamings über HTTP). Ich habe RTSP nur als Beispiel gewählt. Ich kann nicht sagen, ob es in Ihrem speziellen Szenario nützlich sein könnte. Möglicherweise möchten Sie eine weitere SO-Frage zu Streaming-Protokollen stellen. Wikipedia bietet auch einen guten Ausgangspunkt für andere Protokolle - siehe Abschnitte "Protokollprobleme" und "Siehe auch" hier: en.wikipedia.org/wiki/Streaming_Media
MicE

1
Vielen Dank, dies ist bei weitem die einfachste und technischste Erklärung.
Silentsudo
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.