¿Cómo encajan los recursos de transmisión en el paradigma RESTful?

101

Con un servicio RESTful puede crear, leer, actualizar y eliminar recursos. Todo esto funciona bien cuando se trata de algo como los activos de una base de datos, pero ¿cómo se traduce esto en transmisión de datos? (¿O no?) Por ejemplo, en el caso del video, parece una tontería tratar cada cuadro como un recurso que debería consultar uno a la vez. Más bien, establecería una conexión de socket y transmitiría una serie de cuadros. ¿Pero esto rompe el paradigma RESTful? ¿Qué pasa si quiero poder rebobinar o adelantar la transmisión? ¿Es esto posible dentro del paradigma RESTful? Entonces: ¿Cómo encajan los recursos de transmisión en el paradigma RESTful?

Como cuestión de implementación, me estoy preparando para crear un servicio de transmisión de datos de este tipo y quiero asegurarme de hacerlo de la "mejor manera". Estoy seguro de que este problema se ha resuelto antes. ¿Alguien puede señalarme un buen material?

JnBrymn
fuente
2
¿Qué opción elegiste finalmente? ¿Ha mirado gRPc? Admite transmisión bidireccional.
Mac

Respuestas:

80

No logré encontrar materiales sobre la transmisión verdaderamente RESTful ; parece que los resultados se tratan principalmente de delegar la transmisión a otro servicio (lo cual no es una mala solución). Así que haré todo lo posible para abordarlo yo mismo: tenga en cuenta que la transmisión no es mi dominio, pero intentaré agregar mis 2 centavos.

En el aspecto de la transmisión, creo que debemos separar el problema en dos partes independientes:

  1. acceso a recursos de medios (metadatos)
  2. acceso al medio / flujo en sí (datos binarios)

1.) Acceso a los recursos multimedia
Esto es bastante sencillo y se puede manejar de una manera limpia y REST. Como ejemplo, digamos que tendremos una API basada en XML que nos permitirá acceder a una lista de streams:

GET /media/

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

... y también a corrientes individuales:

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.) Acceso al medio / flujo en sí
Este es el bit más problemático. Ya señaló una opción en su pregunta, y es permitir el acceso a los marcos de forma individual a través de una API RESTful. Aunque esto podría funcionar, estoy de acuerdo contigo en que no es una opción viable.

Creo que hay que elegir entre:

  1. delegar la transmisión a un servicio dedicado a través de un protocolo de transmisión especializado (por ejemplo, RTSP)
  2. utilizando las opciones disponibles en HTTP

Creo que la primera es la opción más eficiente, aunque requiere un servicio de transmisión dedicado (y / o hardware). Puede estar un poco al borde de lo que se considera RESTful, sin embargo, tenga en cuenta que nuestra API es RESTful en todos los aspectos y, aunque el servicio de transmisión dedicado no se adhiere a la interfaz uniforme (GET / POST / PUT / DELETE), nuestra API hace. Nuestra API nos permite un control adecuado sobre los recursos y sus metadatos a través de GET / POST / PUT / DELETE, y proporcionamos enlaces al servicio de transmisión (cumpliendo así con el aspecto de conectividad de REST).

La última opción, la transmisión a través de HTTP , puede no ser tan eficiente como la anterior, pero definitivamente es posible. Técnicamente, no es tan diferente de permitir el acceso a cualquier forma de contenido binario a través de HTTP. En este caso, nuestra API proporcionaría un enlace al recurso binario accesible a través de HTTP y también nos informa sobre el tamaño del recurso:

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>

El cliente puede acceder al recurso a través de HTTP utilizando GET /media/1.3gp. Una opción es que el cliente descargue todo el recurso: descarga progresiva HTTP . Una alternativa más limpia sería que el cliente acceda al recurso en fragmentos utilizando encabezados HTTP Range . Para obtener el segundo fragmento de 256 KB de un archivo de 1 MB de tamaño, la solicitud del cliente se vería así:

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

Un servidor que admita rangos respondería con el encabezado Content-Range , seguido de la representación parcial del recurso:

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

Tenga en cuenta que nuestra API ya le dijo al cliente el tamaño exacto del archivo en bytes (1 MB). En el caso de que el cliente no conozca el tamaño del recurso, primero debe llamar HEAD /media/1.3gppara determinar el tamaño; de lo contrario, corre el riesgo de que el servidor responda con 416 Requested Range Not Satisfiable.

Ratones
fuente
2
Vaya ... esta es una gran información. Ha llamado mi atención sobre un par de nuevas formas de pensar en esto. Tampoco conocía el Protocolo de transmisión en tiempo real.
JnBrymn
1
No hay problema, me alegro de haber podido ayudar. Sin embargo, tenga en cuenta que todavía no he tenido la oportunidad de trabajar personalmente con protocolos de transmisión (con la excepción de la transmisión progresiva a través de HTTP). Elegí RTSP solo como ejemplo, no puedo decir si podría ser útil en su escenario específico. Es posible que desee hacer otra pregunta SO sobre protocolos de transmisión específicamente. Wikipedia también ofrece un buen punto de partida para otros protocolos; consulte las secciones "Problemas de protocolo" y "Consulte también" aquí: en.wikipedia.org/wiki/Streaming_Media
MicE
1
Gracias, esta es, con mucho, la explicación más sencilla y técnica.
silentsudo