Шел 2017 год. Где UDP фрагментация? / Блог компании Voximplant / Хабрахабр

VoIP — это термин-зонтик. Набор технологий, протоколов и просто buzzword’ов, которые относятся к передаче голоса (и видео!) по компьютерным сетям (локальным или интернет) вместо телефонных. И да, большая часть телеком-провайдеров всё ещё использует для передачи голоса собственные сети вместо интернет. С недешевыми коробочками, куда втыкаются T1 и E1 провода.

Чаще всего, для айтишников, не работающих в телекоме, VoIP – это связка RTP/RTCP для передачи голоса/видео плюс SIP – для договориться, кому и как передавать. Именно это связка позволяет подключить офисные «SIP телефоны» к Bitrix24 или Asterisk. Оба протокола могут работать как по TCP, так и по UDP. С передачей голоса по RTP вопросов нет: за редчайшим исключением используется UDP протокол, а кодеки компенсируют потерянные пакеты, так что собеседник почти не «квакает» даже не на самом лучшем канале связи. А вот с SIP история более печальная.

Вообще, SIP — это такой HTTP для телефонии. Про него на Хабре есть замечательный двухсерийный пост. Если кто интересуется, очень рекомендую. Ключевое отличие от HTTP, что SIP должен работать в обе стороны всегда. Задача «отправить сообщение с сервера на клиент» решалась в HTTP очень много лет, пережила AJAX, WebSockets, и сейчас наконец-то стабилизировалась в виде HTTP/2. А в SIP эту задачу нужно было решать сразу: не только телефонный аппарат отправлял запрос «вот он я, готов принимать звонки», но и сервер должен был иметь возможность в любой момент сообщить клиенте «а вот тебе и звонок, принимать будешь?».

А у TCP, при всех его достоинствах, есть и недостатки. Например, соединения могут «протухать». Если не поставить маленький keep-alive (а SIP был создан в 1996-м году) и постоянно не отсылать пинги, то «подключение» может оборваться с одной стороны, а вторая сторона этого не заметит. Хорошо, если оборвалось со стороны клиента — он это заметил и переподключился. А если оборвалось со стороны сервера? Нужно ждать, пока у клиента случится keep alive или какой-нибудь другой таймаут и он переподключится. А в это время клиенту звонок.

А еще 20 лет назад, когда это всё создавалось, был очень печальный вопрос переподключения. Для UDP версии SIP клиентам достаточно время от времени (раз в час) посылать пакеты REGISTER, говоря «вот он я, готов принимать звонки». В случае перезагрузки или выключения сервера другой сервер за тем же IP-адресом может работать со всеми этими клиентам. А вот в случае TCP клиентам нужно будет переподключаться. Десять тысяч телефонов здания (обычная ситуация) пошли переподключаться и убили сервер…

В общем, все ждали, что SIP будет по TCP. А он стал по UDP. Сейчас, 20 лет спустя, все больше компаний переключаются на «только по tcp». Тем не менее, огромный парк устройств, клиентов и инфраструктуры ходили по UDP, ходят по UDP и ближайшие несколько лет ходить будут.

А в комбинации «SIP и UDP» есть беда. Собственно, этот пост про нее. Беда называется «фрагментация». Сама по себе фрагментация сетевых пакетов почти безвредна: есть настроенный для сетевой карты MTU, максимальный размер передаваемого за раз пакета. В большинстве случаев это 1500 байт. Для TCP и подавляющего большинства UDP протоколов это никак не влияет: они просто никогда не шлют пакеты больше MTU и используют внутренние механики, чтобы передавать большие объемы данных по кусочкам, терять эти кусочки и пересылать их повторно, если надо.

А SIP — он как HTTP. Текстовый. И в последние годы к простым командам вроде «я тут» и «тебе звонок» добавилась куча дополнительных полей и всяких XML/JSON в пайлоадах. Размер получающихся пакетов стал регулярно выходить за пределы MTU. Начиная с этого момента история становится совсем печальной.

Современный интернет — он, на самом деле, не очень хорошо приспособлен к фрагментированным сетевым пакетам. Производители оборудования и авторы софта резонно полагают, что большинству софта такие пакеты слать не нужно. TCP фрагментирует сам, UDP — это realtime команды, видео и звук. Им не нужно быть больше MTU. Если потеряются, ничего страшного не произойдет. И не очень заморачиваются, насколько хорошо их решения поддерживают фрагментированные пакеты. Свичи могут крешится. «Корпоративные» железки, делающие свои надстройки поверх ethernet/ip, не могут фрагментацию и молча игнорируют пакеты. А у некоторых железок буфер на сборку фрагментированных пакетов — на целых 200 штук. Переполняется он на удивление легко.

Все это мы видим в техподдержке, когда «звонки то работают, а то не работают». Хорошо, когда есть команда инженеров, которые могут запросить у телеком оператора SIP-логи, вдумчиво почитать и ткнуть пальцем в «проблемный» участок. Намного хуже, когда в компании один Asterisk и админ-удаленщик, его обслуживающий. В таком случае «просто магия, иногда звонки не доходят».

Сейчас все стараются использовать SIP по TCP, но проблема отставания инфраструктуры за последние несколько лет встала очень остро. Все больше видео и голосовых звонков совершаются через браузеры (чего стоит только недавно вышедший «Skype для веб»). С какой скоростью развивается веб, мы с вами прекрасно знаем: набежавшие разработчики принесли с собой привычные JSON и XML пайлоады, а видеоконференции на 20-30 человек перестали быть уделом крупных компаний, где бородатые админы могли неделями настраивать циски, «чтобы работало».

Вывод: увидите SIP и UDP в одном месте — будьте осторожны. И при первой возможности переключайте на TCP!

Ссылки позаимствованы вот из этой статьи, которая рассматривает проблему гораздо глубже и тоже рекомендует по возможности использвать TCP

А картинка для привлечения внимания — вот отсюда

Источник