您好,登錄后才能下訂單哦!
高并發實時彈幕是一種互動的體驗。對于互動來說,考慮最多的地方就是:高穩定性、高可用性以及低延遲這三個方面。
高穩定性,為了保證互動的實時性,所以要求連接狀態穩定;
高可用性,相當于提供一種備用方案,比如,互動時如果一臺機器掛了,此時必須保證可以和另外一臺機器連接,這樣就從側面解決了,用戶連接不中斷的問題;
低延遲,彈幕的延遲周期控制在1秒以內,響應是比較快的,所以可以滿足互動的需求。
B站直播彈幕服務架構(下面簡稱GOIM)的出現就是為了解決這一系列的需求。下面將對此進行詳細的介紹。
直播聊天系統本質上也是一種推送系統,所謂推送系統就是,當你發送一條消息時,它可以將這個消息推送給所有人。對于直播彈幕來說,用戶在不斷的發送消息,不斷的進行廣播,當一個房間里面有10萬人時,一個消息就要發出10萬次請求。在GOIM出現之前,也用過另一個名為Gopush的項目,這個項目推出的目的就是進行推送。在此之后,基于一些針對性的應用場景,GOIM對Gopush進行了優化,從而出現在我們視野當中。GOIM主要包含以下幾個模塊(圖1):
1. Client
客戶端。與Comet建立鏈接。
2. Comet
維護客戶端長鏈接。在上面可以規定一些業務需求,比如可以規定用戶傳送的信息的內容、輸送用戶信息等。Comet提供并維持服務端與客戶端之間的鏈接,這里保證鏈接可用性的方法主要是發送鏈接協議(如Socket等)。
3. Logic
對消息進行邏輯處理。用戶建立連接之后會將消息轉發給Logic,在Logic上可以進行賬號驗證。當然,類似于IP過濾以及黑名單設置此類的操作也可以經由Logic進行。
4. Router
存儲消息。Comet將信息傳送給Logic之后,Logic會對所收到的信息進行存儲,采用register session的方式在Router上進行存儲。Router里面會收錄用戶的注冊信息,這樣就可以知道用戶是與哪個機器建立的連接。
5. Kafka(第三方服務)
消息隊列系統。Kafka是一個分布式的基于發布/訂閱的消息系統,它是支持水平擴展的。每條發布到Kafka集群的消息都會打上一個名為Topic(邏輯上可以被認為是一個queue)的類別,起到消息分布式分發的作用。
6. Jop
消息分發。可以起多個Jop模塊放到不同的機器上進行覆蓋,將消息收錄之后,分發到所有的Comet上,之后再由Comet轉發出去。
以上就是GOIM系統實現客戶端建立鏈接,并進行消息轉發的一個具體過程。一開始這個結構并不完善,在代碼層面也存在一些問題。鑒于這些問題,B站提供了一些相關的優化操作。在高穩定性方面,提供了內存優化、模塊優化以及網絡優化,下面是對這些優化操作的介紹。
內存優化
內存優化主要分為以下三個方面:
一個消息一定只有一塊內存
使用Job聚合消息,Comet指針引用
一個用戶的內存盡量放到棧上
內存創建在對應的用戶Goroutine(Go程)中
內存由自己控制
主要是針對Comet模塊所做的優化,可以查看模塊中各個分配內存的地方,使用內存池
模塊優化
模塊優化也分為以下三方面:
消息分發一定是并行的并且互不干擾
要保證到每一個Comet的通訊通道必須是相互獨立的,保證消息分發必須是完全并列的,并且彼此之間互不干擾。
并發數一定是可以進行控制的
每個需要異步處理開啟的Goroutine(Go協程)都必須預先創建好固定的個數,如果不提前進行控制,那么Goroutine就隨時存在爆發的可能。
全局鎖一定是被打散的
Socket鏈接池管理、用戶在線數據管理都是多把鎖;打散的個數通常取決于CPU,往往需要考慮CPU切換時造成的負擔,并非是越多越好。
模塊優化的三個方面,主要考慮的問題就是,分布式系統中會出現的單點問題,即當一個用戶在建立鏈接后,如果出現故障,其余用戶建立的鏈接不能被影響。
測試是實踐過程中最不可缺少的一部分,同時,測試的數據也是用來進行參考比照的最好工具。
圖2是15年末的壓測數據。當時使用了兩臺物理機,平均每臺的在線量是25萬,每個直播每秒的推送數量控制在20-50條內。一般對于一個屏幕來說,40條就可以滿足直播的需求,當時用來進行模擬的推送量是50條/秒(峰值),推送到達數是2440萬/秒。這次的數據顯示,CPU的負載是剛好滿,內存使用量在4G左右,流量約為 3G。從這個數據得出的結論是,真正的瓶頸負載在CPU上。所以,目的很明確,就是將CPU負載打滿(但是不能超負載)。
2015年之后,再次進行優化,將所有內存(堆上的、不可控的)都遷移到棧上,當時只采用了一臺物理機,上面承載了100萬的在線數量。優化效果體現在16年3月的壓測數據(圖3)中,這個數據也是最初直播時,想要測試的一個壓縮狀況。
從圖 3的數據可以看出,優化效果是成倍增加的。當時的目的也是將CPU打滿,可是在實際直播環境中,需要考慮的最本質的問題其實是在流量上,包括彈幕字數、贈送禮物的數量。如果彈幕需要加上一些特殊的需求(字體、用戶等級等),贈送禮物數量過多這樣,都會產生很多流量。所以,直播彈幕優化的最終瓶頸只有流量。
2016年之前,B站的優化重點都放在了系統的優化上,包括優化內存,降低CPU的使用率,可是優化的效果并不顯著,一臺機器的瓶頸永遠是流量。在2016年3月份后,B站將優化重點轉移到了網絡優化上。下面就是B站網絡優化的一些措施。
網絡優化
最初B站的工作內容,主要是以開發為主,為了在結構上面得到擴展,所做的工作就是將代碼盡量完善。但是在實際業務當中,也會遇見更多運維方面的問題,所以,在之后的關注重點上,B站添加了對運維的重點關注。
圖4是B站早期的部署結構。最開始,整套服務是部署在一個IDC上面的(單點IDC),時間一長,這樣的部署結構也逐漸顯現出它的缺陷:
單線IDC流量不足
單點問題
接入率低
這樣的網絡部署往往會造成延遲高、網速卡頓等問題。
針對以上三點問題,B站也對部署結構進行了改善,圖 5是改善過的網絡部署結構,下面將對這個部署結構進行詳細說明。
針對單點IDC流量不足的問題,B站采用了多點IDC接入的方案。一個機房的流量不夠,那么就把它分散到不同的機房,看看效果如何。
對于多點IDC接入來說,專線的成本是非常高昂的,對于創業公司來說,是一塊很大的負擔,所以可以通過一些研發或者是架構的方式來解決多IDC的問題 。針對多IDC的問題,需要優化的方面還有很多,下面列舉出一些B站現有的一些優化方案:
調節用戶最優接入節點
使用Svrlist模塊(圖6.1 )支持,選取距離用戶最近的最穩定的節點,調控IP段,然后進行接入。
IDC 的服務質量監控:掉線率
判斷一個節點是否穩定,需要不斷收集大量的用戶鏈接信息,此時就可以使用監控來查詢掉線率,然后不斷調優,收集最終的結果去做一個拓撲圖(全國范圍),在拓撲圖當中就可以判斷出城市到機房之間的最優線路。
自動切走“失聯”服務器
消息100%的到達率(仍在實現中)
對于彈幕來說,低丟包率是非常重要的。比如,消息是價值上千塊的禮物,此時一旦丟失某些消息,當用戶發禮物時,起到的效果就是,實際在彈幕中顯示出來的效果是,禮物數遠遠少于用戶花費金錢買來的禮物數。這是一個很嚴重的問題。
流量控制
對于彈幕來說,當用戶量到達一定級別時,需要考慮的問題還是流量控制,這也是對于花銷成本的控制,當買的機房的帶寬,是以千兆帶寬為計費標準時,當有超標時,一定要將超標部分的流量切走,以此實現了流量控制的功能。
引入多點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站在部署的時候還優化了故障監控這塊功能,用來保證高可用的服務。故障監控主要為以下幾項:
模擬 Client ,監控消息到達的速率
線上開啟 Ppof ,隨時抓圖分析進程(CPU )狀況
白名單:指定人打印服務端日志
設置白名單,記錄日志信息,收集問題反饋
標注重點問題,及時解決
防止消息重現
服務器負載監控,短信報警
對于GOIM來說,低成本、高效率一直是B站所追求的標準,B站也將對系統進行持續優化和改進,以給用戶最好的直播彈幕體驗。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。