Como os recursos de streaming se encaixam no paradigma RESTful?

101

Com um serviço RESTful, você pode criar, ler, atualizar e excluir recursos. Tudo isso funciona bem quando você está lidando com algo como ativos de banco de dados - mas como isso se traduz em dados de streaming? (Ou não?) Por exemplo, no caso do vídeo, parece bobo tratar cada quadro como um recurso que devo consultar um de cada vez. Em vez disso, eu configuraria uma conexão de soquete e transmitiria uma série de quadros. Mas isso quebra o paradigma RESTful? E se eu quiser retroceder ou avançar o stream? Isso é possível dentro do paradigma RESTful? Então: Como os recursos de streaming se encaixam no paradigma RESTful?

Por uma questão de implementação, estou me preparando para criar esse serviço de streaming de dados e quero ter certeza de que estou fazendo isso da "melhor maneira". Tenho certeza de que esse problema já foi resolvido antes. Alguém pode me indicar um bom material?

JnBrymn
fonte
2
Que opção finalmente você escolheu? Você já olhou para o gRPc? Ele suporta streaming bidirecional.
Mac

Respostas:

80

Não consegui encontrar materiais sobre streaming verdadeiramente RESTful - parece que os resultados são principalmente sobre delegar streaming a outro serviço (o que não é uma solução ruim). Portanto, farei o meu melhor para resolver isso sozinho - observe que streaming não é meu domínio, mas tentarei adicionar meus 2 centavos.

No aspecto de streaming, acho que precisamos separar o problema em duas partes independentes:

  1. acesso a recursos de mídia (metadados)
  2. acesso ao próprio meio / fluxo (dados binários)

1.) Acesso aos recursos de mídia
Isso é bastante direto e pode ser tratado de uma forma limpa e com REST. Como exemplo, digamos que teremos uma API baseada em XML que nos permite acessar uma lista de fluxos:

GET /media/

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

... e também para fluxos individuais:

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.) Acesso ao próprio meio / fluxo
Esta é a parte mais problemática. Você já apontou uma opção em sua pergunta, que é permitir o acesso aos frames individualmente por meio de uma API RESTful. Mesmo que isso funcione, concordo com você que não é uma opção viável.

Eu acho que há uma escolha a ser feita entre:

  1. delegar streaming a um serviço dedicado por meio de um protocolo de streaming especializado (por exemplo, RTSP)
  2. utilizando opções disponíveis em HTTP

Acredito que o primeiro seja a escolha mais eficiente, embora requeira um serviço de streaming dedicado (e / ou hardware). Pode ser um pouco no limite do que é considerado RESTful, no entanto, observe que nossa API é RESTful em todos os aspectos e mesmo que o serviço de streaming dedicado não adira à interface uniforme (GET / POST / PUT / DELETE), nossa API faz. Nossa API nos permite o controle adequado sobre os recursos e seus metadados via GET / POST / PUT / DELETE, e fornecemos links para o serviço de streaming (aderindo assim ao aspecto de conexão do REST).

A última opção - streaming via HTTP - pode não ser tão eficiente quanto a anterior, mas é definitivamente possível. Tecnicamente, não é muito diferente de permitir o acesso a qualquer forma de conteúdo binário via HTTP. Nesse caso, nossa API forneceria um link para o recurso binário acessível via HTTP e também nos informa sobre o tamanho do 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>

O cliente pode acessar o recurso via HTTP usando GET /media/1.3gp. Uma opção é o cliente baixar todo o recurso - download progressivo HTTP . Uma alternativa mais limpa seria o cliente acessar o recurso em partes usando cabeçalhos de intervalo HTTP . Para buscar o segundo fragmento de 256 KB de um arquivo de 1 MB, a solicitação do cliente ficaria assim:

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

Um servidor que oferece suporte a intervalos responderia com o cabeçalho Content-Range , seguido pela representação parcial do recurso:

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

Observe que nossa API já informa ao cliente o tamanho exato do arquivo em bytes (1 MB). No caso de o cliente não saber o tamanho do recurso, ele deve primeiro chamar HEAD /media/1.3gppara determinar o tamanho, caso contrário, estará arriscando uma resposta do servidor com 416 Requested Range Not Satisfiable.

Ratos
fonte
2
Uau ... esta é uma ótima informação. Você chamou minha atenção para algumas novas maneiras de pensar sobre isso. Eu também não conhecia o Real Time Streaming Protocol.
JnBrymn
1
Sem problemas, fico feliz em poder ajudar. No entanto, observe que ainda não tive a chance de trabalhar pessoalmente com protocolos de streaming (com exceção de streaming progressivo via HTTP). Escolhi RTSP apenas como exemplo, não sei dizer se pode ser útil em seu cenário específico. Você pode querer fazer outra pergunta do SO especificamente sobre protocolos de streaming. A Wikipedia também oferece um bom ponto de partida para outros protocolos - consulte as seções "Problemas de protocolo" e "Consulte também" aqui: en.wikipedia.org/wiki/Streaming_Media
MicE
1
Obrigado, esta é de longe a explicação mais simples e técnica.
silentsudo