日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

作者:vivo 互聯(lián)網(wǎng)服務(wù)器團(tuán)隊(duì)-Li Guolin

一、前言

隨著5G時(shí)代的到來(lái),音視頻行業(yè)也可能迎來(lái)一個(gè)行業(yè)的春天,直播則是新視頻行業(yè)一直以來(lái)的一個(gè)重要的產(chǎn)品形態(tài),從最初的秀場(chǎng)直播,游戲直播,到今年由于疫情,目前比較火的在線教育直播,帶貨直播等,各類新的直播形式則是越來(lái)越多的展示在大眾面前。

作為技術(shù)開發(fā)的我們,今天我們一起簡(jiǎn)單的了解一下,如何快速搭建一套最簡(jiǎn)單的直播系統(tǒng),簡(jiǎn)單地了解一下主流直播的架構(gòu)模型。

二、推拉流模型

首先我們先看一張完整的直播推拉流的模型圖,我們可以很清楚地看到直播宏觀上的架構(gòu)模型圖

玩轉(zhuǎn)直播:如何從 0 到 1 構(gòu)建簡(jiǎn)單直播系統(tǒng)

2.1 直播三個(gè)主要模塊

推流模塊

推流模塊主要分為音視頻數(shù)據(jù)的采集,如果是秀場(chǎng)類直播,可以做美顏濾鏡相關(guān)功能,用來(lái)提升直播的畫面品質(zhì)和用戶體驗(yàn),最后通過編碼壓縮,降低音視頻數(shù)據(jù)的體積,最后通過流媒體傳輸協(xié)議將數(shù)據(jù)按照固定格式傳遞到RTMP服務(wù)器,這樣整個(gè)推流端的工作就完成了。

RTMP服務(wù)端模塊

傳統(tǒng)意義上的RTMP服務(wù)器其實(shí)可能就只有轉(zhuǎn)碼的功能,將推流端傳遞過來(lái)的數(shù)據(jù),轉(zhuǎn)成flv等網(wǎng)絡(luò)格式的數(shù)據(jù)文件,方便播放端的觀看,不過目前云商都提供了一整套的解決方案,例如清晰度轉(zhuǎn)碼,內(nèi)容健康檢查,直播封面的生成,數(shù)據(jù)統(tǒng)計(jì),錄制回放等功能,這也是在RTMP服務(wù)器的基礎(chǔ)上,進(jìn)行的業(yè)務(wù)封裝,這樣才能提供一整套的解決方案。

播放端模塊

播放端的邏輯就相對(duì)比較簡(jiǎn)單,簡(jiǎn)而言之就是獲取拉流地址,進(jìn)行音視頻的播放,不過在實(shí)際開發(fā)的過程中,播放端的業(yè)務(wù)工作量和技術(shù)優(yōu)化點(diǎn)都是最多的,如上圖所示的首屏秒開,解碼優(yōu)化,切換直播間等功能,都是需要花費(fèi)大量的精力,根據(jù)業(yè)務(wù)不斷地去演進(jìn)優(yōu)化的。

三、搭建步驟

本入門直播簡(jiǎn)單教程主要分為如下幾個(gè)模塊

搭建直播服務(wù)器

使用OBS進(jìn)行推流

直播流如何觀看

直播間消息的實(shí)現(xiàn)

3.1 搭建直播服務(wù)器

直播服務(wù)器實(shí)時(shí)地將推流端上傳的視頻流進(jìn)行解析和編解碼,以用于支持rtmp、hls或httpflv等直播協(xié)議的觀看端進(jìn)行觀看。

玩轉(zhuǎn)直播:如何從 0 到 1 構(gòu)建簡(jiǎn)單直播系統(tǒng)

當(dāng)前市面上有很多開源的直播服務(wù)器解決方案,如 livego、srs 和 Nginx-rtmp ,亦或者是目前比較主流的云解決方案,目前阿里云,七牛云,騰訊云等都提供了標(biāo)準(zhǔn)的成熟的解決方案,本篇文章旨在快速地搭建一個(gè)簡(jiǎn)單的直播,所以我們可以采用livego這個(gè)開放源代碼的方式去搭建推拉流服務(wù)器,livego 使用純 go 語(yǔ)言編寫,性能高且跨平臺(tái),安裝和使用非常簡(jiǎn)單,支持常用的傳輸協(xié)議、文件格式和編碼格式,或者安裝上文所示,直接在云商開播直播服務(wù)。

安裝 livego 主要有三種方式:1)直接下載二進(jìn)制可運(yùn)行文件;2)從Docker啟動(dòng);3)從源碼編譯。


 

docker run -p 1935:1935 -p 7001:7001 -p 7002:7002 -p 8090:8090 -d gwuhaolin/livego

其中,各個(gè)端口的含義如下:

8090:HTTP 管理訪問監(jiān)聽地址

1935:RTMP 服務(wù)監(jiān)聽地址

7001:HTTP-FLV 服務(wù)監(jiān)聽地址

7002:HLS 服務(wù)監(jiān)聽地址

3.2 使用OBS推流

OBS(Open Broadcaster Software)是一款開源免費(fèi)的提供視頻錄制和直播功能的軟件,去OBS官網(wǎng)下載對(duì)應(yīng)平臺(tái)的軟件進(jìn)行安裝即可。

要想推流,首先要解決的是“推什么”的問題,也就是要明確流的來(lái)源。打開OBS,點(diǎn)擊新建“來(lái)源”按鈕,如下圖中第1步所示,可以看到OBS支持的來(lái)源比較豐富,有媒體源、顯示器采集、瀏覽器和窗口采集等等。此處用現(xiàn)有的mp4文件來(lái)進(jìn)行循環(huán)推流,因此來(lái)源選擇“媒體源”,名稱用默認(rèn)的就行,點(diǎn)擊“確定”后,設(shè)置要播放的視頻文件,然后點(diǎn)擊“確定”即可。

玩轉(zhuǎn)直播:如何從 0 到 1 構(gòu)建簡(jiǎn)單直播系統(tǒng)

然后,要解決的就是“往哪推”的問題,也就是需要有一個(gè)可用的推流地址才行。

前面我們已經(jīng)搭建好了livego直播服務(wù)器,它提供了一個(gè)默認(rèn)推流地址:
rtmp://localhost:1935/live,一個(gè)標(biāo)準(zhǔn)的RTMP服務(wù)器的推流URL類似這種格式:rtmp://domain/AppName/StreamName,但是要想使用該推流地址,需要有授權(quán)的 channelkey 才行。

通過訪問
http://localhost:8090/control/get?room=movie 就可以獲取用于推流的 channelkey,如下所示,其中 data 字段就是此次獲取到的 channelkey。

{ "status": 200, "data": "rfBd56ti2SMtYvSgD5xAV0YU99zampta7Z7S575KLkIZ9PYk"}

到現(xiàn)在,推流地址和 channelkey 都有了,只需要在OBS里面進(jìn)行相關(guān)設(shè)置就可以進(jìn)行推流。首先點(diǎn)擊“控件”的“設(shè)置”按鈕,進(jìn)入設(shè)置面板。

玩轉(zhuǎn)直播:如何從 0 到 1 構(gòu)建簡(jiǎn)單直播系統(tǒng)

然后,選擇“推流”選項(xiàng)。服務(wù)選擇“自定義”,

服務(wù)器設(shè)置為:
rtmp://localhost:1935/live,串流密鑰設(shè)置為前面獲取到的 channelkey:rfBd56ti2SMtYvSgD5xAV0YU99zampta7Z7S575KLkIZ9PYk 。設(shè)置好后,點(diǎn)擊“控件”的“開始推流”按鈕,就可以進(jìn)行推流了。

玩轉(zhuǎn)直播:如何從 0 到 1 構(gòu)建簡(jiǎn)單直播系統(tǒng)

一般情況下,默認(rèn)的輸出配置就足以應(yīng)付大多數(shù)場(chǎng)景了,但是要想獲得更適合自己想要的的直播效果的話,可以在“輸出”選項(xiàng)里設(shè)置“高級(jí)”輸出模式,對(duì)此無(wú)需求的話可以直接跳過本部分。如下圖所示,在高級(jí)輸出設(shè)置界面,可以對(duì)串流、錄像、音頻和回放緩存進(jìn)行配置,其中,最重要的就是對(duì)串流的設(shè)置。編碼器軟件可以選擇 x264 和 QuickSync H.264,使用強(qiáng)大的 x264就可以。“重新縮放輸出”可以設(shè)置輸出的分辨率,默認(rèn)使用原視頻的分辨率。

玩轉(zhuǎn)直播:如何從 0 到 1 構(gòu)建簡(jiǎn)單直播系統(tǒng)

比特率(碼率)的含義是視頻經(jīng)過壓縮編碼后每秒的數(shù)據(jù)量的大小,單位是 Kbps,此處 K=1000。該值越大,每秒推送的視頻數(shù)據(jù)流就越大,視頻質(zhì)量也越高,但是占用的帶寬也更多,可以根據(jù)需要進(jìn)行調(diào)整,一般秀場(chǎng)直播常用2000~2500Kbps就可,游戲直播可能對(duì)碼率的要求比較高一點(diǎn),可以做對(duì)應(yīng)的調(diào)整。

直播推流時(shí),可以使用多種碼率控制方式,主要有CBR、ABR、VBR和CRF。

CBR(Constant Bitrate)恒定碼率,一定時(shí)間范圍內(nèi)比特率基本保持恒定。使用該模式時(shí),在視頻動(dòng)態(tài)畫面較多的場(chǎng)景下,圖像質(zhì)量會(huì)變差,而在靜態(tài)畫面較多的場(chǎng)景下,圖像質(zhì)量又會(huì)變好。

VBR(Variable Bitrate)可變碼率,其碼率可以隨著圖像的復(fù)雜程度的不同而變化。使用該模式時(shí),在圖像內(nèi)容比較簡(jiǎn)單的場(chǎng)景下,分配較少的碼率,而在圖像內(nèi)容復(fù)雜的場(chǎng)景下,則分配較多的碼率。這樣既保證了質(zhì)量,又兼顧到帶寬限制,優(yōu)先考慮到圖像質(zhì)量。

ABR(Average Bitrate)平均比特率,是VBR的一種插值參數(shù)。簡(jiǎn)單場(chǎng)景分配較低碼率,復(fù)雜場(chǎng)景分配足夠碼率,這一點(diǎn)類似VBR。同時(shí),一定時(shí)間內(nèi)平均碼率又接近設(shè)置的目標(biāo)碼率,這一點(diǎn)又類似CBR。可以認(rèn)為ABR是CBR和VBR的折中方案。

CRF(Constant Rate Factor)恒定碼率系數(shù)。CRF值可以理解為對(duì)視頻的清晰度和流暢度期望的一個(gè)固定輸出值,即無(wú)論是在復(fù)雜場(chǎng)景還是在簡(jiǎn)單場(chǎng)景下,都希望有一個(gè)穩(wěn)定的主觀視頻質(zhì)量。

關(guān)鍵幀間隔(Group of Pictures,GOP)指的是一組由一個(gè)I幀、多個(gè)P幀和B幀組成的一個(gè)幀序列。一幀就是視頻中的一個(gè)畫面,其中:

I幀(intra coded picture):最完整的畫面,自帶全部信息,無(wú)需參考其他幀即可解碼,每個(gè)GOP都是以I幀開始;

P幀(predictive coded picture):幀間預(yù)測(cè)編碼幀,需要參考前面的I幀或P幀,才能進(jìn)行解碼,壓縮率較高;

B幀(bipredictive coded picture):雙向預(yù)測(cè)編碼幀,以前幀后幀作為參考幀,壓縮率最高。

對(duì)于普通視頻,加大GOP長(zhǎng)度有利于減小視頻體積,但是在直播場(chǎng)景下,GOP過大會(huì)導(dǎo)致客戶端的首屏播放時(shí)間變長(zhǎng)。GOP越小圖片質(zhì)量越高,建議設(shè)為2秒,最長(zhǎng)不要超過4秒。

3.3 直播流觀看

我們剛剛已經(jīng)搭建完成了RTMP服務(wù)器,并且使用目前比較成熟,功能比較豐富的推流工具OBS進(jìn)行推流,接下來(lái)我們就要解決如何在用戶終端進(jìn)行觀看了的問題。

FLV(Flash Video)是一種網(wǎng)絡(luò)視頻格式,是一種流媒體格式,目前主流的一些直播網(wǎng)絡(luò)使用的流媒體格式比較多的都是flv,它能夠不需要安裝任何插件即可進(jìn)行播放。

3.3.1 小試牛刀:使用VLC工具觀看

VLC 是一款音視頻播放器,可以播放本地媒體,也可以播放網(wǎng)絡(luò)上的媒體,到官網(wǎng)


https://www.videolan.org/index.zh.html 下載對(duì)應(yīng)的安裝包安裝即可。

點(diǎn)擊“媒體”tab下的“打開網(wǎng)絡(luò)串流”選項(xiàng),然后網(wǎng)絡(luò)地址設(shè)置為:


rtmp://localhost:1935/live/movie ,點(diǎn)擊“確定”后就可以看到OBS推流的視頻啦。

玩轉(zhuǎn)直播:如何從 0 到 1 構(gòu)建簡(jiǎn)單直播系統(tǒng)玩轉(zhuǎn)直播:如何從 0 到 1 構(gòu)建簡(jiǎn)單直播系統(tǒng)

使用VLC主要是方便開發(fā)同學(xué)進(jìn)行觀看測(cè)試,例如觀看卡頓的問題,分辨率查看,時(shí)延問題的定位,VLC算是一個(gè)比較專業(yè)的工具,能夠方便我們?nèi)ザㄎ粏栴}和解決問題的

3.3.2 使用flv.js進(jìn)行瀏覽器端的觀看

flv.js是目標(biāo)最為流行的html5的純的JAVAscript,也是目前國(guó)內(nèi)比較主流的瀏覽器終端播放flv格式的解決方案,本小節(jié)我們就使用flv.js進(jìn)行簡(jiǎn)單的播放,打開如下的網(wǎng)址:
http://bilibili.github.io/flv.js/demo/

玩轉(zhuǎn)直播:如何從 0 到 1 構(gòu)建簡(jiǎn)單直播系統(tǒng)

可以看到如圖所示的,將如下streamURL的輸入框輸入
http://127.0.0.1:7001/live/movie.flv 后,點(diǎn)擊switch to MediaDataSource后Load即可播放如下的畫面。

玩轉(zhuǎn)直播:如何從 0 到 1 構(gòu)建簡(jiǎn)單直播系統(tǒng)

3.3.3 直播協(xié)議的簡(jiǎn)單介紹

玩轉(zhuǎn)直播:如何從 0 到 1 構(gòu)建簡(jiǎn)單直播系統(tǒng)

到目前為止,我們已經(jīng)成功的搭建了RTMP小框架,了解了整個(gè)推拉流的完整過程,接下來(lái)我們就需要對(duì)與RTMP協(xié)議幾個(gè)強(qiáng)相關(guān)的直播網(wǎng)絡(luò)傳輸協(xié)議有一個(gè)入門的了解。

國(guó)內(nèi)常見的直播協(xié)議有幾個(gè):

RTMP

HLS

HTTP-FLV

HLS全稱是 HTTP Live Streaming。這是 Apple 提出的直播流協(xié)議。目前,IOS 和 高版本 Android 都支持 HLS,HLS 主要的兩塊內(nèi)容是 .m3u8 文件和 .ts 播放文件。接收服務(wù)器會(huì)將接收到的視頻流進(jìn)行緩存,然后緩存到一定程度后,會(huì)將這些視頻流進(jìn)行編碼格式化,同時(shí)會(huì)生成一份 .m3u8 文件和其它很多的 .ts 文件,HLS的優(yōu)點(diǎn)是跨平臺(tái)性比較好,HTML5可以直接打開播放,移動(dòng)端兼容性良好,缺點(diǎn)也是比較明顯,就是時(shí)延比較高,如果有些直播,例如互動(dòng)性不高的直播,可以使用該協(xié)議,HLS網(wǎng)絡(luò)傳輸格式是非常適合用于點(diǎn)播的場(chǎng)景。

RTMP全稱 Real Time Messaging Protocol,即實(shí)時(shí)消息傳送協(xié)議,對(duì)于開發(fā)者來(lái)說(shuō),我們先明確RTMP是應(yīng)用層協(xié)議,底層是使用的TCP傳輸協(xié)議,這邊我們知道RTMP是音視頻相關(guān)領(lǐng)域的協(xié)議,所以這塊使用TCP作為主要的傳輸層協(xié)議也給后續(xù)RTMP關(guān)于網(wǎng)絡(luò)的各種各樣的演進(jìn),留下了很多的空間,在直播行業(yè),特別是在推流端,RTMP協(xié)議是名副其實(shí)的霸主,基本上所有主流的直播網(wǎng)站都是支持rtmp協(xié)議進(jìn)行推流的,關(guān)于RTMP的具體協(xié)議細(xì)節(jié),后續(xù)文章有具體的分析。

FLV(Flash Video)是 Adobe 公司推出的另一種視頻格式,是一種在網(wǎng)絡(luò)上傳輸?shù)牧髅襟w數(shù)據(jù)存儲(chǔ)容器格式。其格式相對(duì)簡(jiǎn)單輕量,不需要很大的媒體頭部信息。整個(gè) FLV 由 The FLV Header, The FLV Body 以及其它 Tag 組成。因此加載速度極快。采用 FLV 格式封裝的文件后綴為 .flv。

玩轉(zhuǎn)直播:如何從 0 到 1 構(gòu)建簡(jiǎn)單直播系統(tǒng)

流媒體協(xié)議 RTMP, HTTP-FLV, HLS 簡(jiǎn)單對(duì)比:

玩轉(zhuǎn)直播:如何從 0 到 1 構(gòu)建簡(jiǎn)單直播系統(tǒng)

3.3.4 直播中的消息

在秀場(chǎng)直播系統(tǒng)中,如果說(shuō)音視頻功能的實(shí)現(xiàn),是給直播裝扮上了華麗的新裝外表的話,那么直播系統(tǒng)中消息系統(tǒng)的實(shí)現(xiàn),則是整個(gè)直播華麗新裝下的靈魂,如何搭建高可用的直播間消息系統(tǒng),也是每一個(gè)直播系統(tǒng)必須要解決的問題。

在設(shè)計(jì)秀場(chǎng)直播的消息系統(tǒng)之前,我們需要簡(jiǎn)單地梳理一下直播間的消息類型。

通知類消息

例如送禮、彈幕、進(jìn)場(chǎng)、榜單變化、等級(jí)變化等等消息。他們的特征是通知用戶直播間的事件,營(yíng)造直播間氛圍,提升用戶觀看直播的體驗(yàn)。

功能類消息

例如踢人、反垃圾審核、紅包、PK消息等等。這類消息的特征是輔助直播業(yè)務(wù)開展,在流程上串聯(lián)開播端、觀看端、服務(wù)端三個(gè)角色。

我們可以從業(yè)務(wù)角度中,分析出直播間的各類消息雖然因?yàn)闃I(yè)務(wù)形態(tài)各式各樣,最終呈現(xiàn)的形式也是多彩絢麗,但是我們可以從各類的消息展現(xiàn)形式可以分析出,消息從開發(fā)的角度,有如下幾個(gè)特性,我們按照消息是否可丟棄,和實(shí)時(shí)性劃分,我們可以把所有的業(yè)務(wù)消息歸為如下幾類:

玩轉(zhuǎn)直播:如何從 0 到 1 構(gòu)建簡(jiǎn)單直播系統(tǒng)

在直播系統(tǒng)中,秀場(chǎng)直播,帶貨直播的直播間消息信令通信是比較偏多的,主要是因?yàn)闃I(yè)務(wù)性質(zhì)所決定的,秀場(chǎng)直播和帶貨直播這兩類直播的互動(dòng)性相對(duì)比較強(qiáng),玩法也比較多樣,按照我們上圖的分類,每一個(gè)業(yè)務(wù)的消息的可丟棄性和實(shí)時(shí)性要求都不一樣,所以在開發(fā)消息系統(tǒng)的時(shí)候,也需要對(duì)消息進(jìn)行優(yōu)先級(jí)排序,對(duì)消息分發(fā)的實(shí)時(shí)性也要有業(yè)務(wù)性能考量。

剛剛針對(duì)直播間消息實(shí)時(shí)性和不可丟棄性這兩個(gè)屬性做了業(yè)務(wù)上相關(guān)的闡述,不過對(duì)于直播消息而言,第一要素是穩(wěn)定性,消息如何準(zhǔn)確穩(wěn)定地分發(fā)到指定的直播間,也是我們需要考慮的問題之一,直播消息的分發(fā)實(shí)現(xiàn),從總體上說(shuō)可以分為兩種實(shí)現(xiàn)方式,第一是依靠直播間的實(shí)時(shí)通訊(Instant Messaging),也就是我們常說(shuō)的IM消息系統(tǒng),第二個(gè)是依靠http短輪詢,例如客戶端每隔1秒來(lái)請(qǐng)求一次服務(wù)器,服務(wù)器返回這一秒內(nèi)發(fā)生的增量消息信息,客戶端獲取到這些增量信息,再根據(jù)具體的消息業(yè)務(wù)類型,再進(jìn)行相對(duì)業(yè)務(wù)的頁(yè)面UI渲染,這樣就可以了,從技術(shù)上說(shuō),一個(gè)是“推”模型,一個(gè)是“拉”模型,今天我們因?yàn)榇罱ㄒ粋€(gè)簡(jiǎn)單的直播間消息系統(tǒng),我們先用一個(gè)簡(jiǎn)單的"拉"模型進(jìn)行簡(jiǎn)單的實(shí)現(xiàn)。

基本實(shí)現(xiàn)思路:客戶端每隔一個(gè)極短的時(shí)間,例如1秒亦或者更短的時(shí)間,根據(jù)直播間的id來(lái)調(diào)用服務(wù)端的接口,輪詢?cè)撝辈ラg發(fā)生的消息,服務(wù)端這邊我們使用redis的SortedSet的數(shù)據(jù)結(jié)構(gòu)來(lái)存儲(chǔ)消息,其中key是直播間的房間id,score是服務(wù)器接收到該消息事件生成的時(shí)間戳,value可以簡(jiǎn)單地直接存儲(chǔ)該消息序列化后的字符串,這樣可以按照時(shí)間順序地去存儲(chǔ)消息,并且配置過期消息的刪除邏輯,整個(gè)消息的存儲(chǔ)就可以簡(jiǎn)單地搭建起來(lái)。

消息存儲(chǔ)用java的偽代碼所示:

long time = new Date.getTime;try { // redis中插入消息數(shù)據(jù) jedisTemplate.zadd(V_UNIQUE_ROOM_ID, time, JSON.toJSONString(roomMessage)); // 按照概率性的去刪除redis中過期的消息數(shù)據(jù) if (probability) { deleteOverTimeCache(V_UNIQUE_ROOM_ID); } } catch (Exception e) { log.error("message save error", e); }

可以看到消息存儲(chǔ),如果使用redis的sortedSet進(jìn)行存儲(chǔ)還是比較方便的,接下來(lái)我們需要處理就是redis中過期消息的刪除,因?yàn)闊o(wú)效的過期消息是沒有價(jià)值的(所有的消息可以做持久化存儲(chǔ)),redis中如果單一的key存儲(chǔ)的消息過多,也會(huì)導(dǎo)致消息的慢查,和內(nèi)存的使用量不斷增大,這是我們不想看到的,這邊因?yàn)槭鞘纠a,所以簡(jiǎn)單地處理一下刪除邏輯。

private void deleteOverTimeCache(String roomId) { Long totalCount = jedisTemplate.zcard(roomId); log.info("deleteOldTimeCache size is {}", totalCount); if (totalCount < 600) { return; } // 倒序刪除過期數(shù)據(jù) Set<Tuple> tuples = jedisTemplate.zrangeWithScores(roomId, -601, -1); if (CollectionUtils.isNotEmpty(tuples)) { for (Tuple tuple : tuples) { // 這是第一個(gè)-600條的那個(gè)score double score = tuple.getScore; jedisTemplate.zremrangeByScore(roomId, 0d, score); break; } } }

上面的偽代碼probability首先先做一個(gè)概率性的判斷,例如我們做百分之一的隨機(jī)判斷,判斷該次請(qǐng)求是否要進(jìn)行消息的刪除(請(qǐng)注意我們刪除的邏輯是放在插入的邏輯之中的。如果每一次插入都需要判斷是否要?jiǎng)h除過期數(shù)據(jù),會(huì)影響插入的性能)。如果通過概率性判斷后,我們就優(yōu)先判斷某一個(gè)直播間的消息個(gè)數(shù),如果消息個(gè)數(shù)還是比較少的話,則退出刪除邏輯,如果超過消息閥值,則按照時(shí)間倒序刪除已經(jīng)過期的消息。

說(shuō)完了http短輪詢消息的存儲(chǔ)后,我們最后再簡(jiǎn)單地說(shuō)一下客戶端消息查詢實(shí)現(xiàn)邏輯。客戶端通過直播間id和時(shí)間戳兩個(gè)字段來(lái)請(qǐng)求服務(wù)端以查詢直播間消息,其中"時(shí)間戳"是每一次服務(wù)端返回的,這個(gè)時(shí)間戳是漸進(jìn)式的,當(dāng)下一次客戶端來(lái)請(qǐng)求服務(wù)端的數(shù)據(jù)的時(shí)候,都會(huì)帶來(lái)上次服務(wù)端返回的時(shí)間戳,偽代碼如下:

@Override public RoomMessage queryRoomMessages(MessageMessageReq messageMessageReq) { RoomMessage result = new RoomMessage; long timestamp = messageMessageReq.getTimestamp; Set<Tuple> tuples = ; if (timestamp == 0) { // 如果傳遞是0,說(shuō)明這個(gè)客戶端終端是第一次來(lái)輪詢,我們只要返回一個(gè)最近最新的消息返回即可 tuples = jedisTemplate.zrevrangeWithScores(UNIQUE_ROOM_ID, 0, 0); } else // 加上一毫秒,返回后續(xù)的消息,每次返回5個(gè),防止客戶端因?yàn)榈投耸謾C(jī)原因,過多的消息渲染不出來(lái) tuples = jedisTemplate.zrangeByScoreWithScores(UNIQUE_ROOM_ID, timestamp + 1, System.currentTimeMillis, 0, 5); } List<EachRoomMessage> eachRoomMessages = new ArrayList<>; long lastTimestamp = 0L; if (!CollectionUtils.isEmpty(tuples)) { for (Tuple tuple : tuples) { //最后一次循環(huán)后,會(huì)把最后一條消息產(chǎn)生的時(shí)間戳,返回給客戶端,這樣下次客戶端就可以拿著這個(gè)時(shí)間戳來(lái)進(jìn)行查詢 lastTimestamp = new Double(tuple.getScore).longValue; eachRoomMessages.add(JSON.parseobject(tuple.getElement, EachRoomMessage.class)); } } result.setTimestamp(lastTimestamp); result.setEachRoomMessages(eachRoomMessages); return result; }

上述三段比較完整地代碼主要陳述了一個(gè)依賴http短輪詢這種方式快速實(shí)現(xiàn)的直播間的能力,這種方式是比較粗糙的,不過卻是一個(gè)很好的實(shí)現(xiàn)思路,目前我們線上部分業(yè)務(wù)也是根據(jù)這個(gè)輪詢的思想進(jìn)行部分模塊的實(shí)現(xiàn)。

這樣實(shí)現(xiàn)的思路也有一個(gè)小坑,如果有采用該思路去實(shí)現(xiàn)的,可以嘗試去規(guī)避。如果Android客戶端斷網(wǎng)的情況下,輪詢的線程是不會(huì)停止的,例如是晚上8點(diǎn)整斷網(wǎng)的,8點(diǎn)01分恢復(fù)網(wǎng)絡(luò)的,當(dāng)網(wǎng)絡(luò)恢復(fù)的時(shí)候,第一次輪詢就會(huì)導(dǎo)致服務(wù)端返回大量的消息,這邊是需要進(jìn)行處理的,否則會(huì)返回過多的消息,服務(wù)端也會(huì)出現(xiàn)慢查,客戶端因?yàn)殇秩具^期的消息也會(huì)出現(xiàn)部分消息展示區(qū)間出現(xiàn)閃跳。例如公屏區(qū)可能會(huì)"發(fā)瘋"般的出現(xiàn)各類消息,這些可以通過客戶端和服務(wù)端的雙方約定進(jìn)行規(guī)避,例如客戶端當(dāng)出現(xiàn)網(wǎng)絡(luò)問題的時(shí)候,在超過5秒以上,可以把時(shí)間戳置為0,要求服務(wù)端返回最新的直播間消息即可,中間丟失掉的消息,可以在業(yè)務(wù)返回內(nèi)的進(jìn)行丟棄。

四、小結(jié)

本文主要是想讓大家對(duì)直播有一個(gè)初步的了解,了解直播基本的概念模型,一些基礎(chǔ)的概念,后續(xù)我們會(huì)深入直播具體的模塊的學(xué)習(xí),進(jìn)一步去了解直播的原理,也能夠幫助我們更好的做好直播的業(yè)務(wù)。

分享到:
標(biāo)簽:直播 系統(tǒng)
用戶無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定