SFU en cascada: mejora de la escalabilidad y la calidad de los medios en aplicaciones WebRTC

Hay dos dificultades en la implementación de servidores de medios para WebRTC: escala, es decir yendo más allá del uso de un servidor y optimizando las demoras para todos los usuarios de la conferencia. Si bien el fragmentación simple en el espíritu de "enviar a todos los usuarios de la conferencia X al servidor Y" se escala fácilmente horizontalmente, está lejos de ser óptimo en términos de demoras. Distribuir la conferencia entre servidores que no solo están cerca de los usuarios, sino que también están interconectados, parece una solución a ambos problemas. Hoy hemos preparado una traducción de material detallado de Boris Grozev de Jitsi: problemas de las SFU en cascada, con una descripción del enfoque y algunas dificultades, así como detalles de implementación. Vale la pena decir que las conferencias Voximplant también usan SFU ; Actualmente estamos trabajando en la cascada de SFU, que aparecerá en nuestra plataforma el próximo año.


Neuronas de ratón. Imagen NIHD ( CC-BY-2.0 )

Las comunicaciones en tiempo real son muy sensibles a la red: ancho de banda, latencia y pérdida de paquetes. Una disminución en la tasa de bits conduce a una disminución en la calidad del video, un retraso de red prolongado conduce a un retraso prolongado para los usuarios finales. La pérdida de paquetes puede hacer que el sonido sea intermitente y provocar congelaciones en el video (debido a la omisión de cuadros).

Por lo tanto, es muy importante que la conferencia elija la ruta óptima entre los dispositivos / usuarios finales. Cuando solo hay dos usuarios, es fácil: WebRTC utiliza el protocolo ICE para establecer una conexión entre los participantes. Si es posible, los participantes se conectan directamente, de lo contrario se utiliza un servidor TURN. WebRTC puede resolver un nombre de dominio para obtener la dirección de un servidor TURN, por lo que puede seleccionar fácilmente un TURN local basado en DNS, por ejemplo, utilizando las propiedades de AWS Route53 .

Sin embargo, cuando el enrutamiento de múltiples participantes ocurre a través de un servidor central de medios, la situación se complica. Muchos servicios de WebRTC utilizan unidades de reenvío selectivo (SFU) para transferir audio y video entre 3 o más participantes de manera más eficiente.

Problema con una estrella


En la topología en estrella, todos los participantes se conectan a un único servidor a través del cual intercambian transmisiones de medios. Obviamente, la elección de la ubicación del servidor es de gran importancia: si todos los participantes se encuentran en los Estados Unidos, no es una buena idea usar un servidor en Sydney.


Muchos servicios utilizan un enfoque simple que funciona bien en la mayoría de los casos: eligen un servidor más cercano al primer participante en la conferencia. Sin embargo, hay momentos en que esta solución no es óptima. Imagine que tenemos tres participantes de la imagen de arriba. Si un australiano (llamada C) es el primero en unirse a la conferencia, entonces el algoritmo elegirá un servidor en Australia, sin embargo, el servidor 1 en los EE. UU. Será la mejor opción, porque él está más cerca de la mayoría de los participantes.

El escenario descrito no es muy frecuente, pero ocurre. Si suponemos que el usuario está conectado en un orden aleatorio, la situación descrita ocurre con ⅓ de todas las conferencias con 3 participantes, una de las cuales está muy eliminada.

Otro escenario más frecuente: tenemos dos grupos de participantes en diferentes lugares. En este caso, el orden de conexión no es importante, siempre tendremos un grupo de participantes cercanos que se vean obligados a intercambiar medios con un servidor remoto. Por ejemplo, 2 participantes de Australia (C&D) y 2 de EE. UU. (A&B).


Cambiar al servidor 1 no será óptimo para los miembros de C&D. El servidor 2 no es óptimo para A&B. Es decir, no importa qué servidor se use, siempre habrá participantes conectados al servidor remoto (= no óptimo).

Pero si no tuviéramos un solo límite de servidor? Podríamos conectar a cada participante al servidor más cercano, solo quedaría conectar estos servidores.

Solución: en cascada


Posponemos la pregunta de cómo conectar los servidores; Veamos primero cuál será el efecto.


La conexión SFU entre C y D no ha cambiado: el servidor 2 todavía se usa. El servidor 1 se usa para los participantes A y B, y esto obviamente es mejor. Lo más interesante es la conexión entre, por ejemplo, A y C: en lugar de A <=> Servidor 2 <=> C, se utiliza la ruta A <=> Servidor 1 <=> Servidor 2 <=> C.

Efecto implícito en el tipo de cambio.


La mezcla SFU tiene sus ventajas y desventajas. Por un lado, en la situación descrita, el tiempo de intercambio entre los participantes se hace más largo cuando se agregan nuevos saltos en la red. Por otro lado, hay una disminución en este tiempo cuando hablamos de la conexión "cliente" - "primer servidor", porque podemos restaurar el flujo de medios con un retraso menor por el principio de salto por salto.

Como funciona WebRTC usa RTP (generalmente sobre UDP) para transmitir medios. Esto significa que el transporte no es confiable. Cuando se pierde un paquete UDP, puede ignorar la pérdida o solicitar un reenvío (retransmisión) utilizando el paquete RTCP NACK : la elección ya está en la conciencia de la aplicación. Por ejemplo, una aplicación puede ignorar la pérdida de paquetes de audio y solicitar la retransmisión de algunos (pero no todos) paquetes de video, dependiendo de si son necesarios para decodificar cuadros posteriores o no.


Retransmisión de paquetes RTP, servidor único

Cuando hay una conexión en cascada, la retransmisión puede estar limitada al servidor local, es decir, realizado en cada sitio individual. Por ejemplo, en la ruta A-S1-S2-C, si se pierde un paquete entre A y S1, S1 lo notará y solicitará una retransmisión; similar a la pérdida entre S2 y C. E incluso si el paquete se pierde entre servidores, el lado receptor también puede solicitar una retransmisión.


Retransmisión de paquetes RTP, dos servidores. Tenga en cuenta que el Servidor 2 no solicita el paquete 2, porque NACK llegó poco después de enviar el paquete.

El cliente utiliza un búfer de jitter para retrasar la reproducción de video y lograr recibir paquetes retrasados ​​/ retransmitidos. El tamaño del búfer cambia dinámicamente según el tiempo de intercambio entre las partes. Cuando se producen retransmisiones salto por salto, el retraso disminuye y, como resultado, el búfer puede ser más pequeño; como resultado, el retraso general también disminuye.

En resumen: incluso si el tiempo de intercambio entre los participantes es mayor, esto puede conducir a una disminución en el retraso en la transferencia de medios entre los participantes. Todavía tenemos que estudiar este efecto en la práctica.

Presentación de las SFU en cascada: Jitsi Meet Case


Alarma vs. Medios de comunicación


Echemos un vistazo a la alarma. Desde el principio, Jitsi Meet compartió el concepto de un servidor de señalización ( Jicofo ) y un servidor de medios / SFU. Esto permitió que la introducción del soporte en cascada sea relativamente simple. Primero, podríamos manejar toda la lógica de señalización en un solo lugar; En segundo lugar, ya teníamos un protocolo de señalización entre Jicofo y el servidor de medios. Solo necesitábamos expandir un poco la funcionalidad: ya admitíamos múltiples SFU conectadas a un servidor de señalización, teníamos que agregar la capacidad de una SFU para conectarse a muchos servidores de señalización.

Como resultado, aparecieron dos grupos de servidores independientes: uno para instancias de jicofo, el otro para instancias de servidores de medios, vea el diagrama:


Un ejemplo de organización de servidores en AWS con la posibilidad de una cascada entre diferentes centros de datos.

La segunda parte del sistema es la comunicación de puente a puente. Queríamos hacer esta parte lo más simple posible, para que no haya una señalización complicada entre los puentes. Toda alarma va entre jicofo y jitsi-videobridge; La conexión de puente se usa solo para mensajes de audio / video y enlace de datos.

Protocolo Octo


Para gestionar esta interacción, tomamos el protocolo Octo, que envuelve los paquetes RTP en encabezados simples de longitud fija y también le permite enviar mensajes de texto. En la implementación actual, los puentes están conectados por una topología de malla completa (malla completa), pero también son posibles otras topologías. Por ejemplo, use un servidor central (estrella para puentes) o una estructura de árbol para cada puente.

Explicación: en lugar de envolverlo en un encabezado Octo, puede usar la extensión de encabezado RTP, que hará que los flujos entre puentes en RTP puro (S). Las versiones futuras de Octo pueden usar este enfoque.

Segunda explicación: Octo no significa nada. Al principio, queríamos usar un servidor central, y nos recordó a un pulpo. Entonces apareció el nombre del proyecto.

Formato de encabezado de Octo

En la terminología Jitsi, cuando un puente es parte de una conferencia con múltiples puentes, tiene un canal Octo adicional (de hecho, un canal para audio y otro para video). Este canal es responsable de enviar / recibir medios a / desde otros puentes. A cada puente se le asigna un puerto libre para Octo (4096 por defecto), por lo que necesitamos el campo ID de conferencia para manejar múltiples conferencias.

Por el momento, el protocolo no tiene mecanismos de seguridad incorporados y delegamos esta responsabilidad a los niveles inferiores. Esto es lo más cercano que haremos en el futuro cercano, pero por ahora los puentes deben estar en una red segura (por ejemplo, una instancia de VPC de AWS separada).

Simulcast


Simulcast permite a cada participante enviar múltiples transmisiones de medios con diferentes velocidades de bits, mientras que el puente ayuda a determinar cuáles son necesarias. Para que esto funcione correctamente, transferimos todas las transmisiones de transmisión simultánea entre los puentes. Gracias a esto, puede cambiar rápidamente entre transmisiones, ya que el puente local no necesita solicitar una nueva transmisión. Sin embargo, esto no es óptimo desde el punto de vista del tráfico de puente a puente, ya que algunos subprocesos rara vez se usan y solo cargan el ancho de banda sin ningún propósito.

Selección activa de miembros


También queríamos la oportunidad de suscribirnos a un participante / orador activo de la conferencia. Resultó ser simple: enseñamos a cada puente a determinar independientemente el participante principal y luego notificar a nuestros clientes locales. Esto significa que la determinación ocurre varias veces, pero no es costosa y le permite simplificar algunos puntos (por ejemplo, no necesita decidir qué puente debe ser responsable de DSI y preocuparse por el enrutamiento de mensajes).

Selección de puente


En la implementación actual, este algoritmo es simple. Cuando un nuevo participante se une a la conferencia, Jicofo debe determinar qué puente asignarle. Esto se hace en función de la región del participante y la congestión de los puentes. Si en la misma región hay un puente libre, entonces se designa. De lo contrario, se utiliza algún otro puente.

Para obtener más información sobre Octo, consulte la documentación .

Expandir SFU en cascada


Para la implementación, utilizamos máquinas en Amazon AWS. Teníamos servidores (alarmas y medios) en 6 regiones:

  • us-east-1 (Virginia del Norte);
  • us-west-2 (Oregón);
  • eu-west-1 (Irlanda);
  • eu-central-1 (Frankfurt);
  • ap-se-1 (Singapur);
  • ap-se-2 (Sydney).

Utilizamos instancias HAProxy georreferenciadas para determinar la región miembro. El dominio meet.jit.si es administrado por Route53 y se resuelve en la instancia de HAProxy, que agrega la región a los encabezados HTTP de la solicitud enviada. El encabezado se usa más tarde como el valor de la variable config.deploymentInfo.userRegion , que está disponible en el cliente gracias al archivo /config.js .

La interfaz jitsi muestra cuántos puentes se utilizan y a qué usuarios específicos están conectados, con fines de diagnóstico y demostración. Al pasar el cursor sobre la esquina superior izquierda del video local, se mostrará el número total de servidores y el servidor al que está conectado. Del mismo modo, puede ver los parámetros del segundo participante. También verá el tiempo de intercambio entre su navegador y el navegador del interlocutor (parámetro E2E RTT).


Al ver quién está conectado a qué servidor, puede ver si se utiliza en cascada.

Conclusión


Octo apareció originalmente como una prueba A / B. Los primeros resultados fueron buenos, por lo que ahora Octo está disponible para todos. Todavía hay mucho tráfico para atravesarlo y una mirada más cercana al rendimiento; También está previsto utilizar estos desarrollos para soportar conferencias aún más grandes (cuando una SFU ya no es suficiente).

Source: https://habr.com/ru/post/es432708/


All Articles