Как потоковые ресурсы вписываются в парадигму RESTful?

101

С помощью службы RESTful вы можете создавать, читать, обновлять и удалять ресурсы. Все это хорошо работает, когда вы имеете дело с чем-то вроде активов базы данных - но как это преобразовать в потоковую передачу данных? (Или нет?) Например, в случае с видео кажется глупым рассматривать каждый кадр как ресурс, который я должен запрашивать по одному. Скорее я бы установил соединение с сокетом и транслировал серию кадров. Но нарушает ли это парадигму RESTful? Что, если я хочу иметь возможность перематывать поток назад или вперед? Возможно ли это в рамках парадигмы RESTful? Итак: как потоковые ресурсы вписываются в парадигму RESTful?

Что касается реализации, я готовлюсь к созданию такой службы потоковой передачи данных и хочу убедиться, что делаю это «наилучшим образом». Я уверен, что эта проблема уже решалась. Может ли кто-нибудь указать мне на хороший материал?

JnBrymn
источник
2
Какой вариант вы в итоге выбрали? Вы смотрели gRPc? Он поддерживает двунаправленную потоковую передачу.
Mac

Ответы:

80

Мне не удалось найти материалов о действительно RESTful-потоковой передаче - похоже, что результаты в основном касаются делегирования потоковой передачи другому сервису (что неплохое решение). Поэтому я сделаю все возможное, чтобы решить эту проблему сам - обратите внимание, что потоковая передача не является моим доменом, но я постараюсь добавить свои 2 цента.

Что касается стриминга, я считаю, что нам нужно разделить проблему на две независимые части:

  1. доступ к медиаресурсам (метаданные)
  2. доступ к самому носителю / потоку (двоичные данные)

1.) Доступ к медиаресурсам.
Это довольно просто и может быть обработано чистым и RESTful способом. В качестве примера предположим, что у нас будет API на основе XML, который позволяет нам получить доступ к списку потоков:

GET /media/

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

... а также к отдельным потокам:

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.) Доступ к самому носителю / потоку.
Это более проблемный момент. Вы уже указали один вариант в своем вопросе, а именно: разрешить доступ к фреймам индивидуально через RESTful API. Хотя это может сработать, я согласен с вами, что это не жизнеспособный вариант.

Я думаю, что нужно сделать выбор между:

  1. делегирование потоковой передачи выделенной службе через специализированный протокол потоковой передачи (например, RTSP)
  2. использование опций, доступных в HTTP

Я считаю, что первое является более эффективным выбором, хотя для этого требуется выделенная потоковая служба (и / или оборудование). Это может быть немного на грани того, что считается RESTful, однако обратите внимание, что наш API RESTful во всех аспектах, и хотя выделенная потоковая служба не придерживается единого интерфейса (GET / POST / PUT / DELETE), наш API делает. Наш API позволяет нам надлежащим образом контролировать ресурсы и их метаданные с помощью GET / POST / PUT / DELETE, и мы предоставляем ссылки на потоковую службу (таким образом, соблюдая аспект связности REST).

Последний вариант - потоковая передача по HTTP - может быть не таким эффективным, как предыдущий, но определенно возможен. Технически это не сильно отличается от разрешения доступа к любой форме двоичного содержимого через HTTP. В этом случае наш API предоставит ссылку на двоичный ресурс, доступный через HTTP, а также сообщит нам о размере ресурса:

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>

Клиент может получить доступ к ресурсу через HTTP, используя GET /media/1.3gp. Один из вариантов для клиента - загрузить весь ресурс - прогрессивная загрузка HTTP . Более чистой альтернативой было бы для клиента доступ к ресурсу по частям с использованием заголовков диапазона HTTP . Для выборки второго фрагмента файла размером 256 КБ размером 1 МБ клиентский запрос будет выглядеть следующим образом:

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

Сервер, поддерживающий диапазоны, затем ответит заголовком Content-Range , за которым следует частичное представление ресурса:

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

Обратите внимание, что наш API уже сообщил клиенту точный размер файла в байтах (1 МБ). В случае, когда клиент не знает размер ресурса, он должен сначала позвонить HEAD /media/1.3gp, чтобы определить размер, иначе он рискует получить ответ сервера с 416 Requested Range Not Satisfiable.

Мышей
источник
2
Вау ... это отличная информация. Вы привлекли мое внимание к паре новых способов подумать об этом. Я также не знал о протоколе потоковой передачи в реальном времени.
JnBrymn
1
Не проблема, я рад, что смог помочь. Однако обратите внимание, что у меня еще не было возможности лично поработать с протоколами потоковой передачи (за исключением прогрессивной потоковой передачи через HTTP). Я выбрал RTSP просто в качестве примера, я не могу сказать, может ли он быть полезен в вашем конкретном сценарии. Вы можете задать еще один вопрос SO конкретно о протоколах потоковой передачи. Википедия также предлагает хорошую отправную точку для других протоколов - см. Разделы «Проблемы протокола» и «См. Также» здесь: en.wikipedia.org/wiki/Streaming_Media
MicE
1
Спасибо, это, безусловно, самое простое и техническое объяснение.
silntsudo 07