Написать базовый сервер селективной пересылки WebRTC (SFU) на Go с использованием библиотеки pion/webrtc/v4 можно за пару дней, однако при масштабировании до тысяч одновременных комнат всплывают серьезные узкие места открытие десятков тысяч эфемерных UDP-портов ломает сеть контейнеров, выделение памяти в куче на каждый пакет вызывает паузы сборщика мусора, а стандартная ренегоциация SDP приводит к многосекундным черным экранам при переключении собеседников.
В предыдущем разборе архитектуры Slyber TURN Server я подробно рассказал, как мы масштабировали ретрансляцию STUN/TURN по ядрам процессора. Ниже мы рассмотрим внутренний движок маршрутизации медиапотоков Slyber SFU Server и инженерные решения, стоящие за мультиплексированием на одном порту, пересылкой RTP без аллокаций и свапом треков в видеорулетке за доли миллисекунды.
1. Сведение 10 000+ медиапортов к единому порту (:4443)
Традиционные WebRTC медиасерверы выделяют случайный UDP-порт под каждый аудио- и видеотрек, вынуждая администраторов открывать огромные диапазоны в файрволе вроде 10000-60000 и усложняя развертывание в bridge-сетях Docker. В slyber-sfu-server транспортный уровень запускает Pion в режиме ICE-Lite поверх единых мультиплексоров ICEUDPMux и ICETCPMux (RFC 4571):
- Единая точка входа UDP и TCP на порту 4443. Все участники вплоть до 5000 активных комнат отправляют и принимают зашифрованный трафик SRTP через один порт
4443, в то время как HTTP-сигналинг, WHIP/WHEP и телеметрия работают на порту8090. - Автоматический переход на TCP за корпоративными файрволами. Когда браузер подключается из закрытой корпоративной сети, где исходящий UDP заблокирован, Pion прозрачно согласовывает фреймированный ICE-TCP (RFC 4571) поверх того же самого порта
4443. - Буферы сокетов ОС 8 МБ и перезапись публичного IP. При запуске движок увеличивает системные буферы чтения и записи (
net.core.rmem_maxиwmem_max) до 8 МБ и подменяет внешние ICE-кандидаты публичным IPv4-адресом хоста, одновременно выдавая временные HMAC-учетные данные для Slyber TURN Server при необходимости обхода симметричного NAT.
2. Горячий путь RTP без аллокаций с пулом sync.Pool и подсчетом ссылок
В конференц-комнате на 50 участников при пересылке видеопотоков 30 к/с выделение нового среза байтов под каждый входящий RTP-пакет создает непрерывную нагрузку на кучу и вызывает всплески задержек из-за фаз mark-assist сборщика мусора Go. Вместо этого каждый входящий пакет считывается напрямую в заранее выделенный буфер на 1600 байт внутри структуры SlyberPacket, управляемой глобальным пулом sync.Pool и атомарным подсчетом ссылок:
pkt := core.AcquirePacket() // refCount = 1
// Разбор заголовка RFC 3550 и хвостового паддинга на месте без выделения срезов
if !core.ParseRTPHeaderInPlace(pkt) {
pkt.Release()
return
}
// Сохранение пакета в послойный кольцевой буфер NACK и раздача активным DownTrack
room.RouteIncomingPacket(pkt)
pkt.Release()
Каждый пространственный слой (S0, S1, S2) имеет собственный кольцевой буфер PacketRingBuffer на 512 слотов (степень двойки) и независимый фильтр PLICoalescer с интервалом 500 мс. Когда мобильный зритель теряет пакеты, SFU переводит номер последовательности зрителя обратно в исходный номер пакета издателя через ReverseTranslateNACK и мгновенно досылает его из памяти, не нагружая отправителя.
| Подсистема движка | Реализация в Slyber SFU | Эффект в продакшене |
| Мультиплексор ICE-транспорта | Единый порт 4443 ICEUDPMux + RFC 4571 ICETCPMux | Избавляет от 10 000+ эфемерных портов в файрволе |
| Жизненный цикл памяти пакетов | Атомарный sync.Pool с подсчетом ссылок (буферы MTU 1600 Б) | Ноль аллокаций в куче на пакет на горячем пути |
| Simulcast и SVC QoS | Послойные кольцевые буферы NACK + PLICoalescer 500 мс | Предотвращает шторм запросов ключевых кадров при потерях |
| Переключение треков в рулетке | FastSwapRouletteTrack + SeqTimestampRewriter | Смена собеседника <0.4 мс без обмена SDP |
3. Свап в видеорулетке за доли миллисекунды без ренегоциации SDP
В анонимных видеочатах один на один смена собеседника средствами стандартного WebRTC требует полного цикла обмена Offer/Answer и повторного согласования ICE, что приводит к черным экранам на 1–2 секунды. Для комнат профиля roulette_1v1 Slyber SFU Server держит потоки кандидатов прогретыми на входе и переключает зрителей по сигнальной команде roulette_swap (документация протокола сигналинга):
FastSwapRouletteTrackотвязывает существующийDownTrackзрителя отoldUpTrackи привязывает его кnewUpTrackпод гранулярной блокировкой комнаты.SeqTimestampRewriterвычисляет модульные смещения (seqOffset = (lastOutSeq + 1) - firstInSeqиtsOffset = (lastOutTS + 1500) - firstInTS), сохраняя согласованныйTargetSSRCзрителя.- Аппаратный видеодекодер браузера мгновенно начинает отрисовывать поток нового собеседника с монотонными номерами пакетов, нулевыми разрывами и без ренегоциации SDP менее чем за 0.4 мс.
Чтобы узнать, как это же ядро маршрутизации интегрирует диалоговые модели ИИ без серверного транскодирования, прочитайте сопутствующую статью о построении голосовых ИИ-пайплайнов реального времени поверх WebRTC SFU или разверните однобинарный релиз со страницы продукта Slyber SFU Server.