偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

彈幕系統(tǒng)更新的血與淚

云計算
隨著公司直播業(yè)務(wù)的變化,彈幕系統(tǒng)從最初的版本到后來優(yōu)化了三四個版本,這個過程大概持續(xù)了一年的時間,本文將從我司早期的彈幕系統(tǒng)開始給大家介紹整個更新過程的“血與淚 ”。

16年是直播浪潮興起的元年,許多互聯(lián)網(wǎng)公司的業(yè)務(wù)都開始涉足直播內(nèi)容模塊。我目前所在公司接手的第一份工作,就是直播業(yè)務(wù)中的彈幕系統(tǒng)優(yōu)化。隨著公司直播業(yè)務(wù)的變化,彈幕系統(tǒng)從最初的版本到后來優(yōu)化了三四個版本,這個過程大概持續(xù)了一年的時間,本文將從我司早期的彈幕系統(tǒng)開始給大家介紹整個更新過程的“血與淚 ”。

早期彈幕系統(tǒng)

一、基本狀況

1.由PHP + Gateway框架編寫

2.所有的Client ID存放在Redis里面

3.最初由三臺機器掛載在LVS系統(tǒng)后方提供服務(wù)

4.使用多進程的方式,開啟多個worker進程來處理消息傳遞內(nèi)容

二、存在的問題

1.內(nèi)存占用量巨大,單機(4核8G配置)承受500左右的Client就會達到內(nèi)存上限

2.每次發(fā)送消息的時候,每臺機器都需要從Redis里面拿取對應(yīng)房間的所有Client ID;并發(fā)高時,Redis的單進程處理效率和內(nèi)網(wǎng)帶寬就成為瓶頸 。

3.單機的并發(fā)處理能力被消息處理的worker進程數(shù)量限制。同時開啟過多的進程,也是對系統(tǒng)資源的格外浪費。

4.單房間超過2000人的時候,消息的延遲有可能會達到1分鐘左右,這是極其嚴(yán)重的問題。

三、臨時改造

由于需要解決的問題比較緊迫,所以快速做了一些邏輯上的改變和業(yè)務(wù)層面的取舍:

1.對Redis的實例進行了拆分,使用了雙機,單機4實例的方式,分散了Redis的壓力

2.對消息處理worker進程的邏輯做了一些修改,限制了單位時間內(nèi)進行廣播的消息數(shù)量,多余的消息會被丟棄 。

3.對于已經(jīng)完成了直播進入點播狀態(tài)的房間,額外啟用了另外一套彈幕系統(tǒng)來進行分流。

4.單個房間切成多個房間進行消息處理。

四、改造之后的效果

1.Redis壓力大幅度降低

2.單機IO性能壓力降低

3.同樣數(shù)量的機器,可以承載更多的直播房間個數(shù)

 

[[215183]]

 

但是,根本問題并沒有得到解決。在臨時解決壓力問題之后,我們需要花一些時間來重新對彈幕系統(tǒng)進行分析,按照分析后的需求,對新的彈幕系統(tǒng)進行重構(gòu)。

新的彈幕系統(tǒng)

一、新彈幕系統(tǒng)面臨的挑戰(zhàn)

1.單房間人數(shù)較高,依照我們公司直播情況,單房間5 – 10萬人同時在線是會出現(xiàn)的。

2.由于直播內(nèi)容等情況造成的某時間段用戶暴漲。

3.需要盡可能實時到達,延遲過高的話會大大降低互動的實時性。

4.每一條消息,都要遞送大量的長連接。

5.大量長連接的維護機制。

6.在運營的過程中,需要處理用戶黑名單、IP黑名單、敏感詞等需求。

二、新的彈幕系統(tǒng)需求

1.由于內(nèi)存的管理對于PHP來說算是一個短板,對于大并發(fā)且長時間穩(wěn)定不需要經(jīng)常更新維護的系統(tǒng)來說,并非最好的選擇,因此選一門合適的語言是必須的。

2.分布式支持,可以快速的橫向擴展,單房間人數(shù)可以支持到十萬級別。

3.可以方便快捷的對系統(tǒng)進行第三方消息的發(fā)送(例如禮物信息、系統(tǒng)通知等)。

4.盡量使用本地內(nèi)存管理來記錄房間內(nèi)客戶端連接,剩下大量的數(shù)據(jù)交互和查詢時間。

5.并發(fā)支持消息廣播,提高廣播效率。

三、新彈幕系統(tǒng)版本的改造方法

1.選擇當(dāng)前正紅且對高并發(fā)支持良好的Golang作為開發(fā)語言。

2.使用開發(fā)語言進行客戶端連接的管理,且每臺機器只管理自己收到的連接請求。

3.使用并發(fā)的房間內(nèi)廣播邏輯,同時對多人進行廣播。

新彈幕系統(tǒng)改造的相關(guān)經(jīng)驗

下面先對一個模塊細節(jié)進行分析,然后進一步分析模塊上層的調(diào)度邏輯。

一、房間管理

  1. type RoomInfo struct { 
  2. RoomID string //房間ID 
  3. Lock *sync.Mutex //房間操作鎖 
  4. Rows []*RowList //房間多行Slice 
  5. Length uint64 //當(dāng)前房間總節(jié)點數(shù) 
  6. LastChangeTime time.Time //最后一次更新時間 
  7. type RowList struct { 
  8. Nodes []*Node //節(jié)點列表 

由于每個房間都有自己的ID,客戶端建立連接之后,就會被放到一個大廳房間里面。接著,客戶端自己提交RoomID上來,連接會被重新連接到對應(yīng)的房間里面。 每個連接在建立之后,都會被包裝成一個Node,放到Rows里面。

  1. type Node struct { 
  2. RoomID string 
  3. ClientID int64 
  4. Conn *websocket.Conn 
  5. UpdateTime time.Time 
  6. LastSendTime time.Time //最后一次發(fā)送消息時間 
  7. IsAlive bool 
  8. DisabledRead bool//是否已經(jīng)被關(guān)閉了發(fā)言權(quán)限 

每一個Node中,都有一個IsAlive來表示連接是否成功。如果連接斷開,或者因為其他原因強制停止服務(wù)的話,會修改此標(biāo)記狀態(tài)。然后由定時的處理機制將此連接關(guān)閉并從內(nèi)存中清除。 Rows的本質(zhì)就是一組事先設(shè)定了長度的Node Slice。

發(fā)送消息的時候,每一組slice使用一個協(xié)程來順序發(fā)送。同一房間內(nèi)的連接,就可以依照slice分組進行并發(fā)發(fā)送。 發(fā)送的時候,會使用鎖將整個房間鎖住,以防止并發(fā)情況下同一連接混入兩條信息。

二、消息管理

  1. var messageChannel map[string]chan nodeMessage 
  2. func init() { 
  3. messageChannel = make(map[string]chan nodeMessage) 
  4. func sendMessageToChannel(roomId string, nm nodeMessage) error { 
  5. //如果房間不存在,創(chuàng)建一個房間 
  6. if c, ok := messageChannel[roomId]; ok { 
  7. else { 
  8. //創(chuàng)建房間通道 
  9. messageChannel[roomId] = make(chan nodeMessage, 1024) 
  10. messageChannel[roomId] 
  11. //創(chuàng)建房間實例 
  12. roomObj := &RoomInfo{} 
  13. roomObj.RoomID = roomId 
  14. roomObj.Rows = make([]*RowList, 0, 4) 
  15. roomObj.Lock = &sync.Mutex{} 
  16. //創(chuàng)建新的協(xié)程來監(jiān)控房間 
  17. go daemonReciver(messageChannel[roomId], roomObj) 
  18. go timerForClean(messageChannel[roomId]) 
  19. //如果是大廳的話,啟動大廳清理協(xié)程 
  20. if roomId == "" { 
  21. go CleanHall(roomObj) 
  22. return nil 

以上是關(guān)于彈幕信息傳遞的一部分代碼。 首先,每一個房間,都有自己的消息通道,所有的這些通道根據(jù)RoomID為key,記錄在一個叫做messageChannel的map里面。 每次收到消息的時候,都直接把消息丟到channel里面,就可以了。(后面由守護協(xié)程來處理)如果沒有房間通道的話,就建立房間的通道channel,并啟動每個房間的一系列協(xié)程。

三、服務(wù)器管理

這里的方案比較簡單,其實就是建立一個上一層的聊天室即一個房間,所有的服務(wù)器都會主動連接到這里,每一個服務(wù)器收到的信息,就會在這個房間里面廣播到別的機器去。

四、守護協(xié)程們管理

守護協(xié)程處理很多瑣碎的事情,保證房間內(nèi)信息的正常分發(fā)以及房間連接的正常管理。各個守護協(xié)程的功能如下:

1.消息發(fā)送協(xié)程:每個房間配備一個,從channel里面獲取到要發(fā)送到本房間的消息,然后在并發(fā)調(diào)用各個RowList的發(fā)送消息機制。

2.房間整理協(xié)程:因為會有連接斷開、房間更換等修改Node狀態(tài)的行為,所以定期會有房間整理協(xié)程來進行節(jié)點整理,刪除當(dāng)前房間無關(guān)的節(jié)點等以提高消息的發(fā)送效率。

[[215184]]

五、測試相關(guān)

運行環(huán)境:云主機8核16G實例

操作系統(tǒng):Centos7(未進行系統(tǒng)優(yōu)化或參數(shù)調(diào)整)

測試內(nèi)容:單機建立15000 websocket連接,并且發(fā)送消息,進入指定房間(所有連接進入同一房間)。一個客戶端進入房間,發(fā)送一條消息,經(jīng)過敏感詞處理、IP和用戶黑名單處理,然后被廣播到所有節(jié)點。

測試結(jié)果:

CPU占用:保持在5%以下

內(nèi)存占用:2GB(包括操作系統(tǒng)本身開銷)

網(wǎng)絡(luò)占用:峰值10Mb/s左右

發(fā)送效率:15000節(jié)點廣播,100ms – 110ms左右。

根據(jù)測試結(jié)果計算:

完全可以在8核16G的機器上,實現(xiàn)無壓力運行50K并發(fā),峰值接近60 – 70K的處理能力。

六、更多分享

我目前正在嘗試把完成這套彈幕系統(tǒng)的基本功能開源出來。已經(jīng)提取出來了一部分,當(dāng)前的地址為:https://github.com/logan-go/roomManager,感興趣的讀者可以通過鏈接查看。

小結(jié)

彈幕系統(tǒng)給視頻直播/點播增加了更多內(nèi)容的互動娛樂性質(zhì),從最初的A站B站發(fā)展到現(xiàn)在各主流視頻網(wǎng)站APP。如何健康高效的管理彈幕系統(tǒng),也是當(dāng)下視頻行業(yè)需要重視的一門技術(shù)活。

責(zé)任編輯:武曉燕 來源: ucloud博客
相關(guān)推薦

2017-12-22 10:01:42

彈幕直播內(nèi)存

2014-08-01 14:32:29

創(chuàng)業(yè)90后創(chuàng)業(yè)

2018-04-11 15:42:04

開源項目姿勢

2012-12-24 09:18:22

iOSUnity3D

2017-05-11 22:43:53

2025-06-16 04:00:00

Spring彈幕技術(shù)

2025-06-16 01:00:00

彈幕系統(tǒng)架構(gòu)

2015-07-16 12:37:28

彈幕

2011-01-14 16:51:44

Linux內(nèi)核

2019-01-02 16:47:46

Golang彈幕

2019-01-02 16:38:37

Golang彈幕

2019-01-02 16:50:30

Golang彈幕

2019-11-20 18:47:26

物聯(lián)網(wǎng)OTA軟件

2025-08-15 07:36:48

彈幕系統(tǒng)Spring

2010-04-28 15:38:54

2010-12-23 14:17:14

Web 2.0

2018-05-08 09:00:00

系統(tǒng)更新

2019-03-29 09:01:39

彈幕微博Python

2021-06-22 18:28:58

程序員技能開發(fā)者
點贊
收藏

51CTO技術(shù)棧公眾號