web-dev-qa-db-de.com

Wie passen Streaming-Ressourcen in das RESTful-Paradigma?

Mit einem RESTful-Service können Sie Ressourcen erstellen, lesen, aktualisieren und löschen. Das alles funktioniert gut, wenn Sie es mit so etwas wie einem Datenbank-Assets zu tun haben. (Oder doch?) Zum Beispiel erscheint es im Falle von Videos albern, jeden Frame als Ressource zu behandeln, die ich nacheinander abfragen sollte. Eher 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ück- oder vorspulen möchte? Ist dies innerhalb des REST-Paradigmas möglich? Also: Wie passen Streaming-Ressourcen in das RESTful-Paradigma?

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

96
JnBrymn

Es ist mir nicht gelungen, Materialien zu 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 geben, um das Problem selbst in den Griff zu bekommen - beachte, dass Streaming nicht meine Domäne ist, aber ich werde versuchen, meine 2 Cent hinzuzufügen.

Unter dem Aspekt des Streamings müssen wir das Problem meiner Meinung nach in zwei unabhängige Teile aufteilen:

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

1.) Zugriff auf Medienressourcen
Das ist ziemlich unkompliziert und kann auf saubere und RUHIGE Weise gehandhabt werden. Angenommen, 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 Stück. Sie haben bereits auf eine Option in Ihrer Frage hingewiesen, nämlich den Zugriff auf Frames einzeln über eine RESTful-API zuzulassen. Auch wenn dies funktionieren mag, stimme ich Ihnen zu, dass dies keine praktikable Option ist.

Ich denke, dass eine Wahl getroffen werden muss zwischen:

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

Ich glaube, das erstere ist die effizientere Wahl, obwohl es einen dedizierten Streaming-Dienst (und/oder Hardware) erfordert. Es könnte ein wenig am Rande dessen sein, was als REST-konform gilt. Beachten Sie jedoch, dass unsere API in allen Aspekten REST-konform ist und dass 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. Außerdem stellen wir Links zum Streaming-Service bereit (dies entspricht dem Aspekt der Konnektivität von REST).

Die letztere Option - Streaming über HTTP - ist möglicherweise nicht so effizient wie die oben genannte, aber es ist definitiv möglich. Technisch gesehen ist es nicht anders, als den Zugriff auf irgendeine Form von binärem Inhalt über HTTP zuzulassen. In diesem Fall würde unsere API einen Link zu der über HTTP zugänglichen Binärressource 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 mit GET /media/1.3gp Auf die Ressource zugreifen. Eine Möglichkeit besteht darin, dass der Client die gesamte Ressource herunterlädt - progressiver HTTP-Download . Eine sauberere Alternative wäre, dass der Client mithilfe von HTTP Range Headers auf die Ressource in Chunks zugreift. Zum Abrufen des zweiten 256 KB großen Teils einer 1 MB großen Datei würde die Clientanforderung dann folgendermaßen aussehen:

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

Ein Server, der Bereiche unterstützt, antwortet dann mit Content-Range-Header , gefolgt von der Teildarstellung 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 kennen würde, sollte er zuerst HEAD /media/1.3gp Aufrufen, um die Größe zu bestimmen, andernfalls riskiert er eine Serverantwort mit 416 Requested Range Not Satisfiable.

77
MicE