原文:Globo.com’s Live Video Platform for FIFA World Cup 2014- Part I: Delivery and Caching
譯者:杰微刊兼職翻譯汪建
下文改編自環(huán)球網(wǎng)的Leandro Moreira 和Juarez Bochi兩位工程師 2015年九月份在San Francisco市舉辦的NGINX會(huì)議的演講。這篇博客是兩部分的第一部分器瘪,它主要關(guān)注與使用NGINX作為流媒體傳輸和緩存普筹,你可以從YouTube上觀看完整的研究視頻筐乳。
內(nèi)容表
0:03介紹
1:51議程
2:14 2010的架構(gòu)
4:08好的部分–低延遲
4:19問題–缺乏關(guān)鍵點(diǎn)監(jiān)測器
4:44問題–可擴(kuò)展性
5:52國際足聯(lián)2010–關(guān)鍵數(shù)量
6:18移動(dòng)設(shè)備的支持
7:29 HLS協(xié)議如何工作?
9:18 基于HLS協(xié)議的首次實(shí)現(xiàn)
10:14內(nèi)容的生成與分布
10:55首個(gè)解決方案的架構(gòu)
11:12 采用HLS協(xié)議
11:54 HLS緩沖VS RTMP緩沖
12:34監(jiān)測器
13:22儀表板
13:45緩存配置
15:30 OS微調(diào)
17:50從NGINX和HLS中獲益
18:43我們的搭配
0:03介紹
Leandro:早上好逞姿,我叫Leandro辞嗡,這里這位是我的朋友Juarez,我們都受雇于環(huán)球網(wǎng)滞造,我們所在的團(tuán)隊(duì)負(fù)責(zé)提供最近一屆世界杯在互聯(lián)網(wǎng)上的現(xiàn)場直播功能续室,是足球的世界杯,而不是橄欖球谒养。
雖然大家只看到我們兩個(gè)在這里挺狰,但實(shí)際上我們是團(tuán)隊(duì)的一部分,所以今天我們展示的工作不僅僅是由我們完成的,而是由我們整個(gè)令人驚奇的團(tuán)隊(duì)完成的丰泊。
另一件事我們需要提的是薯定,我們只限于對巴西直播,所以瞳购,我們不負(fù)責(zé)向全世界現(xiàn)場直播實(shí)況话侄。
1:51議程
我們希望通過一個(gè)時(shí)間軸來展示我們的工作,向大家展示自從我們加入這個(gè)團(tuán)隊(duì)以來的過去到現(xiàn)在的一些情況苛败。展示如何把以前的視頻平臺(tái)打造成如今的平臺(tái)满葛。讓我們看看過去——在2010年非洲世界杯我們使用了什么技術(shù)。
Juarez:感謝Leandro罢屈,我們將簡要地討論下我們在2010年的時(shí)候的經(jīng)驗(yàn)嘀韧,為什么當(dāng)時(shí)系統(tǒng)工作得不是很好,為什么我們決定采用NGINX缠捌。
2010年锄贷,我們使用了Flash媒體服務(wù)器,作為流媒體視頻直播曼月,它基本上是這樣工作的:
首先谊却,場上的攝像機(jī)將原始視頻信號(hào)發(fā)送給編碼器,然后編碼器會(huì)使用視頻和音頻編解碼并轉(zhuǎn)換成RTMP協(xié)議資源哑芹,我們使用了H.264炎辨,我們通過FMS服務(wù)器使用RTMP協(xié)議將信號(hào)編碼往外推送。
為了將這些信號(hào)傳送給觀眾聪姿,我們將這些信號(hào)發(fā)送到另外一個(gè)服務(wù)器或一個(gè)服務(wù)器集群碴萧,這些服務(wù)器再次使用RTMP協(xié)議將視頻信號(hào)直接傳輸給用戶,用戶通過Flash視頻播放器接收觀看末购,RTMP協(xié)議使用它專屬的端口1935破喻,所以有時(shí)我們會(huì)因?yàn)榉阑饓?dǎo)致一些問題。
大家可以看到我們我們整個(gè)過程都使用了RTMP協(xié)議盟榴,這是一個(gè)有狀態(tài)的協(xié)議曹质,使得它很難做到冗余和故障轉(zhuǎn)移,以及其他的一些缺陷擎场。
4:08好的部分–低延遲
使用RTMP協(xié)議的好處是視頻直播的延遲相當(dāng)?shù)陀鸬拢瑑H僅只有2到5秒。
4:19問題–缺乏關(guān)鍵點(diǎn)監(jiān)測器
除了實(shí)現(xiàn)冗余和故障轉(zhuǎn)移困難以外還有一個(gè)缺點(diǎn)顶籽,就是Flash媒體服務(wù)器是閉源代碼軟件玩般,這意味著我們無法對它進(jìn)行調(diào)試,不能對關(guān)鍵點(diǎn)添加性能監(jiān)測器礼饱,我們能做的僅僅是使用tail命令跟蹤log或使用shell腳本監(jiān)控服務(wù)的運(yùn)行狀態(tài)坏为。
4:44問題–可擴(kuò)展性
由于RTMP是一個(gè)有狀態(tài)的協(xié)議究驴,所以另外一個(gè)問題就是可擴(kuò)展性,如果有若干用戶正在連接者某個(gè)服務(wù)器匀伏,而這個(gè)服務(wù)器宕機(jī)了洒忧,所有在這臺(tái)服務(wù)器的用戶需要重新連接到另外一臺(tái)服務(wù)器。
由于他已經(jīng)處于高負(fù)載狀態(tài)下够颠,第二個(gè)服務(wù)器很可能也會(huì)接著宕掉熙侍,接著所有的服務(wù)器都將產(chǎn)生連鎖效應(yīng)導(dǎo)致宕機(jī)。
當(dāng)我們看到這些發(fā)生時(shí)履磨,我們就看到了我們的聲譽(yù)和金錢在往窗外飛走了蛉抓。
這里大家可以看到一張過去我們正在直播一場比賽的圖表,在中場休息的時(shí)候剃诅,我們遭遇了一個(gè)流量高峰巷送,服務(wù)器就宕機(jī)了,于是我們流失了一半以上的觀眾矛辕。像這種現(xiàn)場直播的事我們不可能有機(jī)會(huì)去恢復(fù)笑跛,我們僅有一次機(jī)會(huì)把事情做好做對。
5:52國際足聯(lián)2010–關(guān)鍵數(shù)量
仍然聊品,我們?nèi)〉昧艘恍┲档米鹁吹臄?shù)字飞蹂,至少對于巴西來說是一個(gè)值得尊敬的數(shù)字。我們有將近300000同時(shí)在線的用戶翻屈,雖然最大比特率還不是很高陈哑,但它的質(zhì)量還算不錯(cuò)。
6:18移動(dòng)設(shè)備的支持
Leandro:上面介紹的是過去伸眶,我們在2012年加入了團(tuán)隊(duì)芥颈,而就在這時(shí),互聯(lián)網(wǎng)一直在成長并且蔓延到智能手機(jī)和平板電腦赚抡,所以瞬間我們很有必要要提供實(shí)時(shí)的視頻到移動(dòng)設(shè)備上。
我們注意到并非所有的移動(dòng)設(shè)備都可以播放RTMP協(xié)議的視頻纠屋,這個(gè)僅僅是Flash的東西涂臣,iphone電話和ipad平臺(tái)屬于IOS系統(tǒng)設(shè)備,他們要求你必須使用HLS協(xié)議去播放直播內(nèi)容售担。
7:29 HLS協(xié)議如何工作赁遗?
HLS是蘋果公司提出的一個(gè)協(xié)議,它的工作原理是這樣的族铆,當(dāng)用戶想要觀看視頻播放時(shí)岩四,視頻播放器首先需要的是一個(gè)播放列表,這個(gè)列表中包含了很多連接的文本文件哥攘,這個(gè)列表連接了其他播放列表剖煌,而且這些列表各自代表著視頻連接的質(zhì)量和播放比特率的不同資源材鹦。
現(xiàn)在該協(xié)議會(huì)根據(jù)當(dāng)前的網(wǎng)絡(luò)速度計(jì)算出哪個(gè)級別質(zhì)量的視頻可以播放,例如耕姊,假如你的移動(dòng)設(shè)備使用的是4G網(wǎng)絡(luò)桶唐,那么你的移動(dòng)設(shè)備網(wǎng)絡(luò)決定了你可以觀看720p的視頻資源,它會(huì)得到720p資源的播放列表茉兰,它包含了一系列視頻片段尤泽。然后播放器開始獲取視頻資源,將緩沖區(qū)填滿规脸,最后它就開始播放視頻了坯约。
接著它會(huì)通過再次調(diào)用720p播放列表去更新播放列表資源,獲取更多的視頻片段莫鸭,此后不斷通過這個(gè)過程循環(huán)獲取其他視頻片段闹丐。所以基本上我們使用基于HTTP協(xié)議的HLS協(xié)議去取代RTMP協(xié)議,這也就意味著用一個(gè)無狀態(tài)的協(xié)議取代原來有狀態(tài)的協(xié)議黔龟。
9:18 基于HLS協(xié)議的首次實(shí)現(xiàn)
在我們第一個(gè)基于HLS協(xié)議實(shí)現(xiàn)的版本中妇智,在視頻端采集工作中我們?nèi)匀徊捎昧讼嗤倪^程,我們?nèi)匀皇褂肦TMP協(xié)議推送視頻流氏身,我們?nèi)匀皇褂昧艘粋€(gè)專用的服務(wù)器巍棱,它可以很容易集成。通過EvoStream你可以使用RTMP協(xié)議進(jìn)行推送蛋欣,你也可以獲取到基于HLS協(xié)議的流資源航徙,這些流資源就是前面我展示給大家的在播放列表中的資源片段。
EvoSteam將這些片段保存到一個(gè)普通的文件夾目錄下面陷虎,然后我們引入了NGINX作為負(fù)載均衡器對負(fù)載進(jìn)行分配〉教ぃ現(xiàn)在,我們可以向蘋果設(shè)備尚猿、基于安卓系統(tǒng)的設(shè)備及安裝了Flash播放器的設(shè)備上進(jìn)行視頻直播窝稿。當(dāng)時(shí)市面上沒有一個(gè)基于HLS協(xié)議的Flash播放器,所以我們必須要自己去做凿掂,這個(gè)挺有趣的伴榔。
10:14內(nèi)容的生成與分配
我們的第一個(gè)基于HLS協(xié)議實(shí)現(xiàn)的版本相對簡單基礎(chǔ),僅僅是使用根目錄并且保證其可用庄萎。讓我們深入研究這部分踪少,我喜歡稱這個(gè)過程為內(nèi)容的產(chǎn)生和分配。我們將結(jié)構(gòu)劃分為前端和后端糠涛,我們的NGINX負(fù)載均衡器只做了很簡單的一些事援奢,我們使用Evostream在指定的目錄下去生成HLS協(xié)議的視頻流,我們也正是使用這個(gè)目錄通過Evostream把視頻資源推給用戶忍捡,這里的目錄就是前面提到的根目錄集漾。
10:55首個(gè)解決方案的架構(gòu)
這個(gè)簡單的解決方案十分地奏效切黔,我們的所有架構(gòu)都是很基礎(chǔ)的,在每個(gè)層都使用多個(gè)負(fù)載均衡器做負(fù)載均衡帆竹,例如像緩存绕娘、認(rèn)證和生成等工作,這種模式工作得很良好栽连。
11:12 采用HLS協(xié)議
在這一點(diǎn)上险领,我們做了一個(gè)實(shí)驗(yàn),我們將HLS協(xié)議作為唯一的協(xié)議秒紧,這個(gè)實(shí)驗(yàn)僅僅面向2%的用戶绢陌。我們發(fā)現(xiàn)結(jié)果相當(dāng)好,于是我們將RTMP協(xié)議換成HLS協(xié)議并面向100%用戶熔恢,至此我們將我們的協(xié)議從多協(xié)議版本變成了單協(xié)議脐湾。
11:54 HLS緩沖VS RTMP緩沖
我們收集了一些指標(biāo)信息看看這個(gè)改變給我們的用戶帶來了更好的體驗(yàn)還是更壞的體驗(yàn),我們發(fā)現(xiàn)使用HLS協(xié)議后的緩沖比RTMP協(xié)議的緩沖好很多。除了緩沖方面,我們還有大量的指標(biāo)信息顯示使用HLS協(xié)議給用戶體驗(yàn)帶來了提升坪蚁。
Juarez:是的,啟動(dòng)時(shí)間更低了闻鉴,平均而言,播放時(shí)間更長了茂洒,我們確信HLS協(xié)議能比RTMP協(xié)議運(yùn)行地更好孟岛。
Leandro:是的,有了這些指標(biāo)信息督勺,我們決定100%地轉(zhuǎn)換成HLS協(xié)議渠羞。
12:34監(jiān)測器
由于我們改成了使用基于HTTP協(xié)議,使用監(jiān)測器將給我們帶來巨大的好處智哀,我們可以安裝一個(gè)logstash軟件去獲取日志信息并且發(fā)送給redis緩存次询。此外,我們再安裝另外一個(gè)logstash將日志信息發(fā)送到Graphite監(jiān)控軟件瓷叫。我們也有一些其他代理渗蟹,使用SNMP協(xié)議去了解CPU的工作情況,并將指標(biāo)信息發(fā)送給Graphite監(jiān)控軟件赞辩。有了這個(gè),我們就可以建立一個(gè)儀表板授艰。
13:22儀表板
我們將這個(gè)儀表板稱為索倫辨嗽。我們通過Graphite監(jiān)控軟件、Rails框架和Angular框架實(shí)現(xiàn)了這個(gè)儀表板淮腾。這不是一件太復(fù)雜或難以做到的事情糟需,但是它確實(shí)是一個(gè)十分有用的儀表板屉佳,因?yàn)槲覀兛梢酝ㄟ^一張圖片看到整塊生產(chǎn)的情況。我們可以看到我們是否有很多緩存沒有命中洲押,它是一個(gè)很標(biāo)準(zhǔn)的儀表板指標(biāo)武花,擁有它事情就好辦多了,當(dāng)我們切換到HLS協(xié)議時(shí)就可以通過這個(gè)觀察緩存指標(biāo)杈帐。
13:45緩存配置
將協(xié)議從RTMP切換成HLS幾乎是完美的体箕,但我們也遇到了一些問題。由于我們使用NGINX作為緩存軟件挑童,當(dāng)我們緩存數(shù)據(jù)時(shí)我們就將精力都放到你的緩存中了累铅,所以你想將所有請求都擋在緩存前不讓他們到達(dá)后端,這種事情是我們常見而且常做的站叼,但我們很容易忽略了一個(gè)很簡單的事情娃兽。比如說,一個(gè)請求可能是請求一個(gè)過期的視頻尽楔,這個(gè)請求就會(huì)被穿透到后端投储,但如果越來越多的請求都是此訪問過期的視頻的話,而NGINX還在處在更新緩沖區(qū)的信息的狀態(tài)阔馋,這時(shí)將會(huì)發(fā)生什么情況玛荞?
如果你沒有將它的配置設(shè)置地合適,這些所有的請求都會(huì)穿透你的緩存層直接導(dǎo)致你的后端處于高負(fù)載情況垦缅。所以別忘了使用proxy_cache_use_stale配置冲泥,特別是在更新時(shí)。
15:30 OS微調(diào)
我們也做了一些負(fù)載測試壁涎,看看我們單獨(dú)一臺(tái)機(jī)器能獲取多少的網(wǎng)絡(luò)流量凡恍,而且我們注意到只是使用了NGINX和我們服務(wù)器需要的軟件,我們雖然有10G的網(wǎng)卡怔球,但我們只能獲取到最多5Gbps的網(wǎng)絡(luò)吞吐量嚼酝,這樣的性能不是很好。
我們開始在互聯(lián)網(wǎng)上查找問題出在哪里竟坛,最終我們解決了此問題闽巩,而且問題不在NGINX上。每當(dāng)一個(gè)請求到達(dá)你的網(wǎng)絡(luò)時(shí)担汤,它會(huì)觸發(fā)一個(gè)中斷涎跨,而這需要做一些處理,我不知道這個(gè)問題是不是所有服務(wù)器都會(huì)出現(xiàn)崭歧,但如果你不特意在我們的服務(wù)器上進(jìn)行配置隅很,你將會(huì)發(fā)現(xiàn)這個(gè)問題,因?yàn)樗械恼埱蠖寂艿酵粋€(gè)CPU上去了率碾。所以我們將這個(gè)問題解決了而且使用了irqbalance服務(wù)叔营,然后屋彪,我們就能夠達(dá)到10Gbps的吞吐量了。
然后我們意識(shí)到我們其實(shí)可以獲取到更多的比特流量绒尊,但使用了irqbalance服務(wù)畜挥,我們丟失了很多包,經(jīng)過進(jìn)一步深入研究婴谱,我們發(fā)現(xiàn)使用CPU的親和力是更好的方式蟹但。
Juarez:是的,我們?yōu)槊總€(gè)網(wǎng)卡都創(chuàng)建了若干個(gè)中斷勘究,每個(gè)中斷都被固定到一個(gè)CPU上矮湘,所以我們用此方式替代了原來一個(gè)CPU處理所有中斷,這時(shí)就可以將負(fù)載分散到多個(gè)CPU上口糕,通過這種方式我們可以將網(wǎng)卡的吞吐量提高到網(wǎng)卡的極限缅阳。
Leandro:是的,因?yàn)槲覀冇袃蓚€(gè)網(wǎng)卡景描,我們可以把他們結(jié)合在一起十办,這樣每臺(tái)機(jī)器就有了20Gbps的吞吐量。
Juarez:所以主要的結(jié)論就是超棺,我們不需要對NGINX本身做調(diào)整向族,而僅僅是對操作系統(tǒng)微調(diào),NGINX就能工作的異常成功棠绘。
17:50從NGINX和HLS中獲益
Leandro:來個(gè)總結(jié)件相,通過將協(xié)議從RTMP換成HLS和使用NGINX我們擺脫了端口被防火墻阻止的情況,因?yàn)槲覀兌际鞘褂肏TTP協(xié)議端口80氧苍。NGINX給了我們神奇的緩存夜矗,它也讓我們系統(tǒng)擁有容易的可擴(kuò)展性,因?yàn)樗皇桥c另一個(gè)機(jī)器或虛擬機(jī)熱插拔的事让虐。我們能在用戶體驗(yàn)上取得更好的成功紊撕,因?yàn)镠LS協(xié)議擅長根據(jù)用戶帶寬確定哪個(gè)比特率的流資源。而且我們也很喜歡儀表板赡突,它讓我們掌握整個(gè)系統(tǒng)的運(yùn)作对扶。
18:43我們的搭配
這些就是我們的搭配,擁有80個(gè)節(jié)點(diǎn)惭缰,而且我們使用了CentOS浪南。
這篇博客是兩部分的第一部分,重點(diǎn)是使用NGINX為流媒體進(jìn)行傳輸和緩存漱受。第二部分很快也會(huì)發(fā)布出來络凿,它主要討論環(huán)球網(wǎng)團(tuán)隊(duì)如何使用搭載了LUA第三方模塊的NGINX來為視頻平臺(tái)搭建微服務(wù)。