高併發實時彈幕是一種互動的體驗。對於互動來講,考慮最多的地方就是:高穩定性、高可用性以及低延遲這三個方面。跨域
高穩定性,爲了保證互動的實時性,因此要求鏈接狀態穩定;緩存
高可用性,至關於提供一種備用方案,好比,互動時若是一臺機器掛了,此時必須保證能夠和另一臺機器鏈接,這樣就從側面解決了,用戶鏈接不中斷的問題;服務器
低延遲,彈幕的延遲週期控制在1秒之內,響應是比較快的,因此能夠知足互動的需求。網絡
B站直播彈幕服務架構(下面簡稱GOIM)的出現就是爲了解決這一系列的需求。下面將對此進行詳細的介紹。session
圖1架構
直播聊天系統本質上也是一種推送系統,所謂推送系統就是,當你發送一條消息時,它能夠將這個消息推送給全部人。對於直播彈幕來講,用戶在不斷地發送消息,不斷地進行廣播,當一個房間裏面有
10 萬人時,一個消息就要發出 10 萬次請求。在 GOIM 出現以前,也用過另外一個名爲 Gopush
的項目,這個項目推出的目的就是進行推送。在此以後,基於一些針對性的應用場景,GOIM 對 Gopush
進行了優化,從而出如今咱們視野當中。GOIM 主要包含如下幾個模塊(圖 1):併發
Kafka(第三方服務)
消息隊列系統。Kafka 是一個分佈式的基於發佈/訂閱的消息系統,它是支持水平擴展的。每條發佈到
Kafka 集羣的消息都會打上一個名爲 Topic(邏輯上能夠被認爲是一個 queue)的類別,起到消息分佈式分發的做用。運維
Router
存儲消息。Comet 將信息傳送給 Logic 以後,Logic 會對所收到的信息進行存儲,採用
register session 的方式在 Router 上進行存儲。Router 裏面會收錄用戶的註冊信息,這樣就能夠知道用戶是與哪一個機器創建的鏈接。異步
Logic
對消息進行邏輯處理。用戶創建鏈接以後會將消息轉發給 Logic ,在 Logic
上能夠進行帳號驗證。固然,相似於 IP 過濾以及黑名單設置此類的操做也能夠經由 Logic 進行。分佈式
Comet
維護客戶端長連接。在上面能夠規定一些業務需求,好比能夠規定用戶傳送的信息的內容、輸送用戶信息等。Comet
提供並維持服務端與客戶端之間的連接,這裏保證連接可用性的方法主要是發送連接協議(如 Socket 等)。
Client
客戶端。與 Comet 創建連接。
Jop
消息分發。能夠起多個 Jop 模塊放到不一樣的機器上進行覆蓋,將消息收錄以後,分發到全部的
Comet 上,以後再由 Comet 轉發出去。
以上就是 GOIM 系統實現客戶端創建連接,並進行消息轉發的一個具體過程。一開始這個結構並不完善,在代碼層面也存在一些問題。鑑於這些問題,B
站提供了一些相關的優化操做。在高穩定性方面,提供了內存優化、模塊優化以及網絡優化,下面是對這些優化操做的介紹。
內存優化
內存優化主要分爲如下三個方面:
1.一個消息必定只有一塊內存
使用 Job 聚合消息,Comet 指針引用。
2.一個用戶的內存儘可能放到棧上
內存建立在對應的用戶 Goroutine(Go 程)中。
3.內存由本身控制
主要是針對 Comet 模塊所作的優化,能夠查看模塊中各個分配內存的地方,使用內存池。
模塊優化
模塊優化也分爲如下三方面:
1.消息分發必定是並行的而且互不干擾
要保證到每個 Comet 的通信通道必須是相互獨立的,保證消息分發必須是徹底並列的,而且彼此之間互不干擾。
2.併發數必定是能夠進行控制的
每一個須要異步處理開啓的 Goroutine(Go 協程)都必須預先建立好固定的個數,若是不提早進行控制,那麼
Goroutine 就隨時存在爆發的可能。
3.全局鎖必定是被打散的
Socket 連接池管理、用戶在線數據管理都是多把鎖;打散的個數一般取決於
CPU,每每須要考慮 CPU 切換時形成的負擔,並不是是越多越好。
模塊優化的三個方面,主要考慮的問題就是,分佈式系統中會出現的單點問題,即當一個用戶在創建連接後,若是出現故障,其他用戶創建的連接不能被影響。
測試是實踐過程當中最不可缺乏的一部分,同時,測試的數據也是用來進行參考比照的最好工具。
圖2
圖
2 是 15 年底的壓測數據。當時使用了兩臺物理機,平均每臺的在線量是
25 萬,每一個直播每秒的推送數量控制在 20-50 條內。通常對於一個屏幕來講,40 條就能夠知足直播的需求,當時用來進行模擬的推送量是 50
條/秒(峯值),推送到達數是 2440 萬/秒。此次的數據顯示,CPU 的負載是恰好滿,內存使用量在 4G 左右,流量約爲
3G。從這個數據得出的結論是,真正的瓶頸負載在 CPU 上。因此,目的很明確,就是將 CPU 負載打滿(可是不能超負載)。
圖3
2015 年以後,再次進行優化,將全部內存(堆上的、不可控的)都遷移到棧上,當時只採用了一臺物理機,上面承載了
100 萬的在線數量。 優化效果體如今 2016 年 3 月的壓測數據(圖 3)中,這個數據也是最初直播時,想要測試的一個壓縮情況。
從圖
3 的數據能夠看出,優化效果是成倍增長的。當時的目的也是將 CPU
打滿,但是在實際直播環境中,須要考慮的最本質的問題實際上是在流量上,包括彈幕字數,贈送禮物的數量。若是彈幕須要加上一些特殊的需求(字體、用戶等級等),贈送禮物數量過多這樣,都會產生不少流量。因此,直播彈幕優化的最終瓶頸只有流量。
2016 年以前,B 站的優化重點都放在了系統的優化上,包括優化內存,下降
CPU 的使用率,但是優化的效果並不顯著,一臺機器的瓶頸永遠是流量。在 2016 年 3 月份後,B 站將優化重點轉移到了網絡優化上。下面就是 B 站網絡優化的一些措施。
網絡優化
最初 B 站的工做內容,主要是以開發爲主,爲了在結構上面獲得擴展,所作的工做就是將代碼儘可能完善。可是在實際業務當中,也會碰見更多運維方面的問題,因此,在以後的關注重點上,B
站添加了對運維的重點關注。
圖 4 是 B 站早期的部署結構。最開始,整套服務是部署在一個 IDC 上面的(單點
IDC),時間一長,這樣的部署結構也逐漸顯現出它的缺陷:
單線 IDC 流量不足
單點問題
接入率低
這樣的網絡部署每每會形成延遲高、網速卡頓等問題。
針對以上三點問題,B 站也對部署結構進行了改善,圖 5 是改善過的網絡部署結構,下面將對這個部署結構進行詳細說明。
圖 5
針對單點 IDC 流量不足的問題,B 站採用了多點 IDC 接入的方案。一個機房的流量不夠,那麼就把它分散到不一樣的機房,看看效果如何。
對於多點 IDC 接入來講,專線的成本是很是高昂的,對於創業公司來講,是一塊很大的負擔,因此能夠經過一些研發或者是架構的方式來解決多
IDC 的問題 。針對多 IDC 的問題,須要優化的方面還有不少,下面列舉出一些 B 站現有的一些優化方案:
1.調節用戶最優接入節點
使用 Svrlist 模塊(圖 6.1)支持,選取距離用戶最近的最穩定的節點,調控
IP 段,而後進行接入。
2.IDC 的服務質量監控:掉線率
判斷一個節點是否穩定,須要不斷收集大量的用戶連接信息,此時就可使用監控來查詢掉線率,而後不斷調優,收集最終的結果去作一個拓撲圖(全國範圍),在拓撲圖當中就能夠判斷出城市到機房之間的最優線路。
3.自動切走「失聯」服務器
4.消息 100%的到達率(仍在實現中)
對於彈幕來講,低丟包率是很是重要的。好比,消息是價值上千塊的禮物,此時一旦丟失某些消息,當用戶發禮物時,起到的效果就是,實際在彈幕中顯示出來的效果是,禮物數遠遠少於用戶花費金錢買來的禮物數。這是一個很嚴重的問題。
5.流量控制
對於彈幕來講,當用戶量到達必定級別時,須要考慮的問題仍是流量控制,這也是對於花銷成本的控制,當買的機房的帶寬,是以千兆帶寬爲計費標準時,當有超標時,必定要將超標部分的流量切走,以此實現了流量控制的功能。
引入多點 IDC 接入以後,電信的用戶依舊能夠走電信的線路,可是能夠將模塊在其餘機房進行部署,讓移動的一些用戶能夠鏈接移動的機房。這樣就保證了,不一樣地區不一樣運營商之間,最優網絡選取的問題。
但是解決了最優網絡的選取,卻帶來了跨域傳輸的問題。好比在數據收集時,Comet
模塊將數據反饋到 Logic,Logic
進行消息分發時,數據便會跨機房傳輸。有些公司的機房是經過專線進行傳輸,這樣成本將會很是高。因此,爲了節約成本就只能走公網的流量,可是公網的穩定性是否高、是否高可用,都是須要考慮的。當流量從電信的機房出去以後,通過電信的交換機,轉到聯通的交換機,而後到達聯通的機房,就會存在跨運營商傳輸的問題,好比丟包率高,所以,跨運營商傳輸帶來的問題仍是很是嚴重的。
爲了解決這個可能存在的風險,能夠嘗試在聯通機房接入一條電信的線路(帶寬能夠小一點),「看管」電信的模塊,讓來自不一樣運營商的流量,能夠走本身的線路。作了這樣的嘗試以後,不只下降了丟包率,還知足了對穩定性的基本要求,而且成本消耗也不高。但是,這樣的方案也不能說是百分百的完美,由於就算是同運營商之間的通信,也會存在城市和城市之間某個交換機出現故障的狀況,對於這樣的狀況,B
站採起的方法是同時在 IDC-1 與 IDC-2(圖 5)之間部署兩條電信線路,作了這樣的備份方案以後,通暢程度以及穩定性都有很是明顯的提高。
針對上述過程當中出現的一些問題,前期,須要對每一個線路的穩定性進行測試。爲了測試每一條線路的穩定性,能夠把
Comet 放入各個機房中,並將 Comet
之間的通信方式彙總成一個連接池(連接池裏能夠放多個運營商的多條線路),做爲網絡連接能夠將它配置成多條線路,用模塊檢測全部的 Comet
之間的通信,以及任何線路傳輸的穩定性,若是說通暢的話,則保證這個連接是能夠用的。(這裏面有不少線路,因此必定會選擇通暢的那條線路進行傳輸,這樣,就能夠判斷哪條線路是通暢的。)這樣一來,流量進行傳輸時,就有多條線路能夠進行選擇,三個運營商中,總有一個是能夠服務的。
綜合這些問題,B 站又對結構進行了從新優化。(這個結構剛剛作完,目前尚未上線,還須要通過一些測試。)
首先是
Comet 的連接,以前採用的是 CDN、智能 DNS
。但實際上,有些運營商基站會緩存路由表,因此即使將機器遷移走,部分用戶也並不能同時遷移走。而
DNS 解析這一塊,也並不是徹底可靠,並且一旦趕上問題,解決的流程又很長,這樣下來,體驗效果是十分糟糕的。其次是 List
,將其部署在一箇中心機房,客戶端採用的是 WEB 接口的服務,讓客戶端訪問這個服務,就能夠知道該與哪些服務器進行鏈接。將 IP
List(Comet)部署在多個機房,能夠將多個機房收集的值反饋給客戶端(好比:哪些線路通暢)讓客戶端本身選擇與那個機器進行鏈接。
如圖 6.2 。圖中將 IP 段進行了城市的劃分,將某一個城市的一些用戶信息連接到一個羣組(GroupID),羣組下有一個或多個
Comet ,把屬於這個羣組的物理機所有分給 Comet 。
圖
7 是再次優化的結構,仍是將 Comet 所有放在 IDC 機房中,消息的傳輸再也不使用
push(推)的方式,而是經過
pull(拉)的方式,將數據拉到中心機房(源站),作一些在線處理以後,再統一由源站進行數據推送。固然,這裏要十分注意中心機房的選取,中心機房的穩定性是十分重要的。除此以外,B
站在部署的時候還優化了故障監控這塊功能,用來保證高可用的服務。故障監控主要爲如下幾項:
1.模擬 Client ,監控消息到達的速率
2.線上開啓 Ppof ,隨時抓圖分析進程(CPU)情況
3.白名單:指定人打印服務端日誌
設置白名單,記錄日誌信息,收集問題反饋
標註重點問題,及時解決
防止消息重現
4.服務器負載監控,短信報警
低成本、高效率一直是 B 站所追求的標準,B 站將對 GOIM 系統進行持續優化和改進,以給用戶最好的直播彈幕體驗。