Cascading SFUs: Meningkatkan skalabilitas dan kualitas media dalam aplikasi WebRTC

Ada dua kesulitan dalam menyebarkan server media untuk WebRTC: penskalaan, mis. melampaui menggunakan satu server dan mengoptimalkan penundaan untuk semua pengguna konferensi. Sementara pecahan sederhana dalam semangat "kirim semua pengguna konferensi X ke server Y" dengan mudah menskala secara horizontal, itu jauh dari optimal dalam hal keterlambatan. Mendistribusikan konferensi di antara server yang tidak hanya dekat dengan pengguna, tetapi juga saling berhubungan - terdengar seperti solusi untuk kedua masalah. Hari ini kami menyiapkan terjemahan materi terperinci dari Boris Grozev dari Jitsi: masalah cascading SFU, dengan deskripsi pendekatan dan beberapa kesulitan, serta detail implementasi. Perlu dikatakan bahwa konferensi Voximplant juga menggunakan SFU ; Kami saat ini sedang mengerjakan cascading SFU, yang akan muncul di platform kami tahun depan.


Neuron tikus. Gambar NIHD ( CC-BY-2.0 )

Komunikasi waktu-nyata sangat sensitif terhadap jaringan: bandwidth, latensi, dan kehilangan paket. Penurunan bitrate menyebabkan penurunan kualitas video, penundaan jaringan yang lama menyebabkan penundaan yang lama bagi pengguna akhir. Kehilangan paket dapat membuat suara terputus-putus dan menyebabkan pembekuan pada video (karena bingkai dilewati).

Oleh karena itu, sangat penting bagi konferensi untuk memilih rute optimal antara perangkat / pengguna akhir. Saat hanya ada dua pengguna, mudah - WebRTC menggunakan protokol ICE untuk membuat koneksi antara para peserta. Jika memungkinkan, peserta terhubung secara langsung, jika tidak, server HIDUP digunakan. WebRTC dapat menyelesaikan nama domain untuk mendapatkan alamat server TURN, sehingga Anda dapat dengan mudah memilih TURN lokal berdasarkan DNS, misalnya, menggunakan properti AWS Route53 .

Namun, ketika perutean beberapa peserta terjadi melalui satu server media pusat, situasinya menjadi rumit. Banyak layanan WebRTC menggunakan Unit Penerusan Selektif (SFU) untuk mentransfer audio dan video antara 3 atau lebih peserta secara lebih efisien.

Masalah dengan bintang


Dalam topologi bintang, semua peserta terhubung ke satu server di mana mereka bertukar aliran media. Jelas, pilihan lokasi server sangat penting: jika semua peserta berada di AS, menggunakan server di Sydney bukanlah ide yang baik.


Banyak layanan menggunakan pendekatan sederhana yang berfungsi dengan baik dalam banyak kasus: mereka memilih server yang lebih dekat dengan peserta pertama dalam konferensi. Namun, ada kalanya solusi ini tidak optimal. Bayangkan kita memiliki tiga peserta dari gambar di atas. Jika orang Australia (Penelepon C) adalah orang pertama yang bergabung dalam konferensi, maka algoritme akan memilih server di Australia, namun Server 1 di AS akan menjadi pilihan terbaik, karena dia lebih dekat dengan sebagian besar peserta.

Skenario yang dijelaskan tidak terlalu sering, tetapi memang terjadi. Jika kita mengasumsikan bahwa pengguna terhubung dalam urutan acak, maka situasi yang dijelaskan terjadi dengan ⅓ dari semua konferensi dengan 3 peserta, salah satunya sangat dihapus.

Skenario lain dan lebih sering: kami memiliki dua kelompok peserta di lokasi yang berbeda. Dalam hal ini, urutan koneksi tidak penting, kami akan selalu memiliki sekelompok peserta yang lokasinya dekat yang dipaksa untuk bertukar media dengan server jarak jauh. Misalnya, 2 peserta dari Australia (C&D) dan 2 dari Amerika Serikat (A&B).


Beralih ke Server 1 tidak akan optimal untuk anggota C&D. Server 2 tidak optimal untuk A&B. Artinya, apa pun server yang digunakan, akan selalu ada peserta yang terhubung ke server jarak jauh (= tidak optimal).

Tetapi jika kita tidak memiliki batas server tunggal? Kita bisa menghubungkan setiap peserta ke server terdekat, itu hanya akan menghubungkan server-server ini.

Solusi: Cascading


Kami menunda pertanyaan tentang bagaimana menghubungkan server; pertama mari kita lihat apa efeknya.


Koneksi SFU antara C dan D tidak berubah - Server 2 masih digunakan. Server 1 digunakan untuk peserta A dan B, dan ini jelas lebih baik. Yang paling menarik adalah hubungan antara, misalnya, A dan C: alih-alih A <=> Server 2 <=> C, rute A <=> Server 1 <=> Server 2 <=> C digunakan.

Efek implisit pada nilai tukar


Campuran SFU memiliki pro dan kontra. Di satu sisi, dalam situasi yang dijelaskan, waktu pertukaran antara peserta menjadi lebih lama ketika lompatan baru pada jaringan ditambahkan. Di sisi lain, ada penurunan saat ini ketika kita berbicara tentang koneksi "klien" - "server pertama", karena kita dapat memulihkan aliran media dengan penundaan yang lebih rendah dengan prinsip hop-by-hop.

Bagaimana cara kerjanya? WebRTC menggunakan RTP (biasanya melalui UDP) untuk mengirim media. Ini berarti bahwa transportasi tidak dapat diandalkan. Ketika paket UDP hilang, Anda dapat mengabaikan kehilangan atau meminta pengiriman ulang (pengiriman ulang) menggunakan paket RTCP NACK - pilihan sudah ada di hati nurani aplikasi. Sebagai contoh, suatu aplikasi dapat mengabaikan hilangnya paket audio dan meminta pengiriman ulang beberapa (tetapi tidak semua) paket video, tergantung pada apakah mereka diperlukan untuk memecahkan kode frame berikutnya atau tidak.


Pengiriman ulang paket RTP, satu server

Ketika ada cascading, pengiriman ulang mungkin terbatas pada server lokal, yaitu, dilakukan pada setiap situs individu. Misalnya, dalam rute A-S1-S2-C, jika suatu paket hilang antara A dan S1, maka S1 akan memperhatikan hal ini dan meminta pengiriman ulang; mirip dengan kehilangan antara S2 dan C. Dan bahkan jika paket tersebut hilang antara server, sisi penerima juga dapat meminta pengiriman ulang.


Pengiriman ulang paket RTP, dua server. Perhatikan bahwa Server 2 tidak meminta paket 2, karena NACK tiba segera setelah mengirim paket.

Klien menggunakan buffer jitter untuk menunda pemutaran video dan mengatur untuk menerima paket yang ditunda / dikirim kembali. Ukuran buffer berubah secara dinamis tergantung pada waktu pertukaran antara para pihak. Ketika transmisi ulang hop-by-hop terjadi, penundaan menurun, dan sebagai hasilnya, buffer mungkin lebih kecil - sebagai hasilnya, penundaan keseluruhan juga berkurang.

Singkatnya: bahkan jika waktu pertukaran antara para peserta lebih tinggi, ini dapat menyebabkan penurunan keterlambatan dalam mentransfer media antara para peserta. Kami belum mempelajari efek ini dalam praktiknya.

Memperkenalkan Cascading SFUs: Jitsi Meet Case


Alarm vs. Media


Mari kita lihat alarmnya. Sejak awal, Jitsi Meet membagikan konsep server pensinyalan ( Jicofo ) dan server media / SFU. Ini memungkinkan pengenalan dukungan kaskade relatif sederhana. Pertama, kita bisa menangani semua logika pensinyalan di satu tempat; kedua, kami sudah memiliki protokol pensinyalan antara Jicofo dan server media. Kami hanya perlu sedikit memperluas fungsionalitas: kami sudah mendukung beberapa SFU yang terhubung ke satu server pensinyalan, kami harus menambahkan kemampuan satu SFU untuk terhubung ke banyak server pensinyalan.

Akibatnya, dua kumpulan server independen muncul: satu untuk instance jicofo, lainnya untuk instance server media, lihat diagram:


Contoh pengorganisasian server di AWS dengan kemungkinan kaskade antara berbagai pusat data.

Bagian kedua dari sistem adalah komunikasi bridge-to-bridge. Kami ingin membuat bagian ini sesederhana mungkin, sehingga tidak ada pensinyalan rumit antara jembatan. Semua alarm beralih antara jicofo dan jitsi-videobridge; Koneksi jembatan hanya digunakan untuk pesan audio / video dan tautan data.

Protokol Octo


Untuk mengelola interaksi ini, kami menggunakan protokol Octo, yang membungkus paket RTP dalam header panjang tetap sederhana, dan juga memungkinkan Anda mengirim pesan teks. Dalam implementasi saat ini, jembatan dihubungkan oleh topologi sepenuhnya mesh (full mesh), tetapi topologi lain juga mungkin. Misalnya, gunakan server pusat (bintang untuk jembatan) atau struktur pohon untuk setiap jembatan.

Penjelasan: Alih-alih membungkusnya dalam header Octo, Anda dapat menggunakan ekstensi header RTP, yang akan membuat aliran antar jembatan pada RTP murni (S). Octo versi mendatang dapat menggunakan pendekatan ini.

Penjelasan Kedua: Octo tidak berarti apa-apa. Pada awalnya, kami ingin menggunakan server pusat, dan itu mengingatkan kami pada gurita. Maka nama untuk proyek muncul.

Format Octo Header

Dalam terminologi Jitsi, ketika sebuah jembatan adalah bagian dari konferensi dengan banyak jembatan, ia memiliki saluran Octo tambahan (pada kenyataannya, satu saluran untuk audio dan satu untuk video). Saluran ini bertanggung jawab untuk mengirim / menerima media ke / dari jembatan lain. Setiap jembatan diberi porta bebas untuk Octo (4096 secara default), jadi kita perlu bidang ID Konferensi untuk menangani beberapa konferensi.

Saat ini, protokol tidak memiliki mekanisme keamanan bawaan dan kami mendelegasikan tanggung jawab ini ke tingkat yang lebih rendah. Ini adalah hal terdekat yang akan kami lakukan dalam waktu dekat, tetapi untuk saat ini jembatan harus berada dalam jaringan yang aman (misalnya, instance AWS VPC terpisah).

Simulcast


Simulcast memungkinkan setiap peserta untuk mengirim beberapa aliran media dengan bitrate yang berbeda, sementara bridge membantu menentukan mana yang dibutuhkan. Agar ini berfungsi dengan benar, kami mentransfer semua streaming simulcast di antara jembatan. Berkat ini, Anda dapat dengan cepat beralih di antara aliran, karena jembatan lokal tidak perlu meminta aliran baru. Namun, ini tidak optimal dari sudut pandang lalu lintas jembatan ke jembatan beberapa utas jarang digunakan dan hanya memuat bandwidth tanpa tujuan.

Seleksi Anggota Aktif


Kami juga menginginkan kesempatan untuk berlangganan ke peserta / pembicara aktif konferensi. Ternyata menjadi sederhana - kami mengajar setiap jembatan untuk secara independen menentukan peserta utama, dan kemudian memberi tahu klien lokal kami. Ini berarti bahwa definisi muncul beberapa kali, tetapi tidak mahal dan memungkinkan Anda untuk menyederhanakan beberapa poin (misalnya, Anda tidak perlu memutuskan jembatan mana yang harus bertanggung jawab untuk DSI dan khawatir tentang perutean pesan).

Temukan jembatan


Dalam implementasi saat ini, algoritma ini sederhana. Ketika seorang peserta baru bergabung dengan konferensi, Jicofo harus menentukan jembatan mana yang akan ditugaskan kepadanya. Ini dilakukan berdasarkan wilayah peserta dan kemacetan jembatan. Jika di wilayah yang sama ada jembatan gratis, maka diangkat. Kalau tidak, beberapa jembatan lain digunakan.

Untuk informasi lebih lanjut tentang Octo, lihat dokumentasi .

Perluas cascading SFU


Untuk penyebaran, kami menggunakan mesin di Amazon AWS. Kami memiliki server (alarm dan media) di 6 wilayah:

  • us-east-1 (Virginia Utara);
  • us-west-2 (Oregon);
  • eu-west-1 (Irlandia);
  • eu-central-1 (Frankfurt);
  • ap-se-1 (Singapura);
  • ap-se-2 (Sydney).

Kami menggunakan instance HAProxy yang dirujuk secara geografis untuk menentukan wilayah anggota. Domain meet.jit.si dikelola oleh Route53 dan menyelesaikan ke instance HAProxy, yang menambahkan wilayah ke header HTTP permintaan yang dikirim. Header kemudian digunakan sebagai nilai variabel config.deploymentInfo.userRegion , yang tersedia di klien berkat file /config.js .

Antarmuka jitsi menunjukkan berapa banyak jembatan yang digunakan dan ke mana pengguna tertentu dilampirkan - untuk tujuan diagnostik dan demonstrasi. Melayang di sudut kiri atas video lokal akan menunjukkan jumlah total server dan server yang terhubung. Demikian pula, Anda dapat melihat parameter peserta kedua. Anda juga akan melihat waktu pertukaran antara browser Anda dan browser lawan bicara (parameter E2E RTT).


Dengan melihat siapa yang terhubung ke server mana, Anda dapat melihat apakah cascading digunakan.

Kesimpulan


Octo awalnya muncul sebagai tes A / B. Hasil pertama bagus, jadi sekarang Octo tersedia untuk semua orang. Masih ada banyak lalu lintas untuk melewatinya dan melihat lebih dekat kinerja; juga direncanakan untuk menggunakan perkembangan ini untuk mendukung konferensi yang bahkan lebih besar (ketika satu SFU tidak lagi cukup).

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


All Articles