[Перевод] Сигнальные и транспортные протоколы WebRTC: срываем покровы
Недавно мы нашли на просторах интернета интересную статью, которая рассказывает технические подробности «передачи информации» между браузерами. Адаптированный для Хабра перевод — под катом.
Где здесь сигнальный, а где транспортный уровень?
WebRTC как протокол не включает в себя механизмы «сигнализации». Это значит, что вам, как разработчику, нужно будет позаботиться о них самостоятельно.
Первый шаг — это выбрать протокол. А если быть более точным, то два протокола — транспортный и сигнальный. В большинстве случаев мы не видим разницу (или не хотим её видеть), но иногда она очень важна. Недавно я получил вопрос к одному из постов, и это подтолкнуло меня написать объяснение.
Веб-браузеры и транспортные протоколы WebRTC
Транспортный протокол необходим нам, чтобы отправлять сообщения с одного устройства на другое. В данном случае не имеет значения, что находится внутри сообщения или как сообщение структурировано — только то, что оно может быть отправлено. А потом получено.
HTTP/1.1
Пять лет назад браузеры были простые, если мы говорим о протоколах. По сути, у нас был HTTP/1.1 и все хаки поверх него, известные как XHR, SSE, BOSH, Comet. Если вам интересно узнать больше о механиках, оставьте комментарий, и я постараюсь объяснить в следующих статьях — хотя вы легко сможете найти объяснение сами, если немного погуглите.
Я называю группу решений на ряду с HTTP/1.1 — костылями. Эти решения используют HTTP/1.1, потому что в то время просто не было альтернативы, но они делают это способом, который не имеет никакого технического смысла.
Да, вы можете использовать REST. Но, опять же, это второстепенная деталь по отношению к HTTP/1.1.
После этого появились три технологии: WebSocket, WebRTC и, совсем недавно, HTTP/2.
WebSocket
WebSocket был добавлен, чтобы делать то, что HTTP/1.1 делать не может. Обеспечить двунаправленный механизм, где оба — клиент и веб-сервер — могут отправлять друг другу сообщения. Что это за сообщения, что они означают, какой тип формата они поддерживают — решает разработчик веб-страницы.
Также есть socket.io или менее популярный SockJS. Оба предлагают механику на стороне клиента, которая эмулирует WebSocket в случаях, когда он не может быть использован.
Когда ваш WebSocket работает великолепно, socket.io и SockJS тоже великолепны. Но иногда он работает не великолепно (больше об этом ниже, под частью HTTP/2).
WebRTC Data Channel
В некоторой степени, Data Channel используется в WebRTC для сигналирования.
Да. Вам будет нужно договориться об используемых IP-адресах, а перед этим использовать ICE. А для этого вам будет нужен дополнительный сигнальный и транспортный уровень (список вот в этом посте). После установки соединения, вы можете использовать data channel в качестве сигнального уровня.
Data Channel можно использовать для сигналирования непосредственно между двумя устройствами, или через посредников (в зависимости от задач).
Зачем использовать Data Channel в качестве транспортного протокола?
- Уменьшить задержку в вашем сигналировании. Data Channel, теоретически, самое быстрое, что вы можете сделать.
- Снизить нагрузку на сервер. Теперь он не будет получать все сообщения только чтобы перенаправить их куда-нибудь — вы будете отправлять ему то, что предназначено именно ему.
- Увеличить уровень конфиденциальности/безопасности личных данных — когда вы не отправляете сообщения через сервер, это значит, что он не будет подглядывать в то, что отправляется — или даже не будет замечать, что какой-то обмен сообщениями идет.
Но, по правде говоря, такой вариант используется редко. В мире WebRTC транспортный уровень важен ДО установки соединения, когда DataChannel еще недоступен. А использовать DataChannel одного соединения как транспортный уровень для сигналирования другого — это странно.
HTTP/2
Я уже писал о HTTP/2 раньше. Но с тех пор HTTP/2 распространился ещё больше и стал ещё популярнее.
HTTP/2 устраняет много ограничений, которые присутствуют в HTTP/1.1. Поэтому он может стать хорошим претендентом для протоколов сигнального уровня на всё ближайшее время.
Как HTTP/2 может влиять на потребности в WebSocket, хорошо описал Алан Денис.
WebRTC Signaling Protocols
«Сигналирование» — это то, где вы выражаете себя. Или ваш сервис. Вы хотите, чтобы один пользователь смог установить связь с другим. Или с группой людей, которые присоединяются к виртуальной комнате. Вы решаете, какие типы сообщений вам нужны, что они значат, на что они похожи и так далее.
Это ваш сигнальный протокол.
В отличие от транспортного протокола, вы ограничены не тем, что позволяет браузер, а тем, чего пытаетесь достигнуть.
Рассмотрим три главных сигнальных протокола, которые часто используются с WebRTC.
SIP
Я ненавижу SIP. Никогда им по-настоящему не интересовался.
У него есть сфера применения, особенно когда дело касается телефонии, классических голосовых и видео-сервисов. Тем не менее я нахожу SIP слишком раздутым, сложным и ненужным — по крайней мере, для большинства случаев, с которыми ко мне обращаются люди.
SIP пришел из мира телефонии. Его основной транспорт был UPD. Затем для него были добавлены TCP и TLS как транспортные протоколы. Затем и SCTP подтянулся. Разбираться в них не имеет смысла, поскольку вы не можете использовать их через браузер. Поэтому WebSocket добавили как SIP-транспорт и просто назвали это «SIP через WebSocket». SIP через WebSocket стандартизировали раньше, чем WebRTC (который всё ещё не стандартизировали), и, кроме прочего, он уже имеет свое собственное RFC. Почему все вышесказанное важно? Потому что использовать SIP через WebSocket можно только вместе с WebRTC.
Это о SIP. И если вы знаете SIP, любите его или нуждаетесь в нем, вы можете использовать его как протокол сигнального уровня для WebRTC.
XMPP
Я ненавижу XMPP.
Но не совсем понимаю, почему. Возможно, потому что когда я что-нибудь говорю о нем плохое, все матёрые фанаты/фолловеры/фанатики протокола XMPP бросаются защищать его в комментариях. А меня это смешит.
XMPP весь сфокусирован вокруг информации о статусе пользователя и быстрых сообщений. Если это единственные требования, то XMPP действительно выигрывает — особенно, когда разработчик уже знает, что можно сделать с помощью XMPP.
Если вы достаточно любите XMPP, не забудьте ответить в комментариях, — это внизу.
Проприетарщина
Я ненавижу NIH. Несмотря на это, собственный сигнальный протокол имеет много преимуществ.
Очень часто всё, что вы хотите, это просто посадить двух пользователей на «одну страницу». Не больше. Я знаю, что сильно упрощаю, но если не упрощать, то вы будете таскать с собой всю избыточность протокола общего назначения, которая вам никогда не пригодится.
Во многих других случаях вы действительно не хотите добавлять ещё один веб-сервер только для работы с сигналированием. Вы хотите, чтобы один сервер обслуживал ваше веб приложение целиком. Так вы приходите к своему собственному протоколу сигнального уровня. Хотя вы можете его так не называть. Или не думать о нем как о протоколе сигнального уровня.
Как сделать выбор?
Всегда начинайте с протокола сигнального уровня.
SIP нужно использовать, если есть какая-то инфраструктура или есть внешние сервисы, к которым вы хотите подключаться. Если нет нужды, тогда пропустите.
Если вы любите XMPP, или нуждаетесь в функциях информации о статусе пользователя и быстрых сообщений, тогда используйте его.
Если сервис, в который вы добавляете WebRTC, имеет собственную логику, возможно, у него уже есть сигналирование. Поэтому вы просто добавляете необходимые сообщения к проприетарному сигналированию.
Во всех других случаях мой совет — использовать проприетарное решение для сигналирования, который точно отвечает вашим требованиям. Можно даже использовать для этого SaaS-решение.