HOW DISCORD HANDLES TWO AND HALF MILLION CONCURRENT VOICE USERS USING WEBRTC
Introduction
- 這篇文章描述Discord如何建立聲音/影像多人溝通頻道,以及其背後用到的技術。
- LINK
Guilding
聲音/影像多人溝通頻道需要支援多人(1000人)同時在線,因此比較適合使用Client-Server架構,Peer-to-Peer架構較不適合。
這裡的理解是如果使用P2P架構來實作多人頻道,假設頻道有N個使用者,則每個Client需與N-1個人建立連線,總共會有N*(N-1)個連線被建立。而這樣的花費非常高。
使用Client-Server架構還有個好處是Client的流量都會先經過Server Routing到其他Client,能夠避免Client的資訊被洩漏。
Client architecture
Discord跑在不同平台上
- Web(Chrome/Firefox)
- App(Windows/MacOS/Linux)
- Phone(iOS/Android)
為了要支援跨平台的連線,Discord使用了WebRTC協定。WebRTC適合用於即時通訊,並且可以傳遞聲音、影像、資料等等資訊。
Discord的Web平台直接使用了WebRTC,而App和Phone平台則使用了基於WebRTC 函示庫程式碼的C++ Media Engine,增加了一些客製化的功能。這代表在App和Phone平台上能夠使用一些特殊功能。 舉例來說:
- 抑制了Windows的 auto-ducking功能:
- auto-ducking: 當在Windows使用通訊裝置時,會自動降低其他應用程式的音量。這對於在遊戲中溝通不太好。
- 當頻道沒有聲音時,自動減少CPU使用率和網路頻寬。
然而使用客製化版本的WebRTC也代表,每當WebRTC更新時,客製化的函示庫可能也需要做一些調整。
Making it Our Own
這裡講述了一些客製化的詳細功能,並指出其與一般的WebRTC協定的差異。
- WebRTC基於Session Description Protocol(SDP),用於一開始建立連線,傳送Participant的基本資訊。
- 而客製化的Library可以使用較底層的Library function,來減少建立連線時傳遞的資訊。
- WebRTC會透過 Interactive Connectivity Establishment (ICE) 來在Client之間傳遞訊息。
- 客製化的Library不使用ICE,而是使用Discord自己的Relay Media Server。
- WebRTC使用Secure RealTime Transport Protocol(SRTP),用來加密資訊。而加密方法使用Datagram Transport Layer Security(DTLS),一個基於TLS的方法。
- 客製化的Library可以自己實作這些功能。而Discord使用了Salsa20用來更快的加密。
Backend Architecture
Discord後端建立了三種Server來服務頻道溝通,分別是:
- Discord Gateway
- Discord Guild Server
- Discord Voice Server
這些都是使用Elixir語言寫的。
當Client在線上時,會與Discord Gateway建立Websocket連線。
- Client會從這個websocket連線中獲取最新的channel, guild等資訊。
當Client加入一個語音頻道時,Client會更新他的Voice state,並把最新資訊透過websocket連線傳送到Gateway。
接著,Client會被指定一個Voice Server並與他連線。語音頻道其他人的聲音會透過Voice Server傳到Client。
Note: 同個Guild中的所有Channel,會被連線到同個Voice Server。Guild 是由多個使用者組成的群組,裡面可以建立多個語音頻道。
- 當此Client是第一個加入語音頻道的人,會由Guild Server指定一個新的Voice Server給他。
Assigning a Voice Server
- 每個Voice Server會定期回報他的狀況,確保沒有斷線。而這些狀況資訊都會由一個Service Discovery Service接收並儲存,Discord使用
etcd
。 - 當有新的連線被建立時,Discord Guild Server會透過Service Discovery service找出現在在線,而且使用率最低的Voice Server。
- Guild Server同時會將連線資訊傳給Voice Server,也會把Voice Server資訊傳給Clients。
- Client在收到資訊後會與新的Voice Server建立第二個WebSocket連線,用來與Voice Server傳遞建立連線相關的資訊。
Discord Voice Server由兩個Component組成:
- A Signaling Component
- SFU (selective forwarding Unit)
Signaling Component用來控制SFU,並負責產生加密密鑰,轉送資訊等等。
SFU負責轉送聲音及影像資訊給Clients。
- SFU同時也負責管理RTCP(Real Time Control Protocol)
- RTCP會蒐集Client的連線狀況,讓Server可以決定要轉送何種品質的聲音及影像資訊。
- SFU同時也負責管理RTCP(Real Time Control Protocol)